[comp.sys.sgi] Distinguishing "true" MIPS box from DECstation at compile time

moraes@cs.toronto.edu (Mark Moraes) (12/16/89)

bin@primate.wisc.edu (Brain in Neutral) writes:
># if mips
># if ultrix
>	DECstation
># else
>	true MIPS
># endif
># endif

Not so fast. SGI also defines "mips" on the Iris4D machines -- why
not, it's the CPU they use.

One possible solution, seen to work on our Iris4D (Irix3.2), our
DS3100s (Ultrix3.1), and our M/120 (Riscos4.0:

#ifdef mips
# ifdef ultrix
#  define ULTRIX_MIPS
#  define arch "ultrix-mips"
# endif
# ifdef sgi
#  define IRIS4D
#  define arch "iris4d"
# endif
# ifndef arch
   /*
    * Must be MIPSCo MIPS. Anyone know a way to differentiate between
    * RISCOS4.0 and UMIPS via cpp?
    */
#  define MIPS
#  define arch "mips"
# endif
#endif

Then one can use the symbols MIPS, IRIS4D, or ULTRIX_MIPS.

Note: this will presumably change once vendors start shipping truly
ANSI compatible compilers -- ANSI prohibits this sort of random
pollution of the namespace. (It'll be __mips__ or suchlike, and life
will become even more complicated, as people try to keep code
backwards compatible with things like"#if defined(mips) ||
defined(__mips__)"))

Another solution is to stick a wrapper script around cc, and get it to
define the symbols you want. The shell script I use for our SGI
machines is enclosed below.

*Soapbox on*

It is probably much better to ifdef on specific features that one
needs (eg.  BSD_SIGNALS, JOB_CONTROL, DIRENT, SHMEM, etc) than on a
specific vendor type, considering the way the zillion and one
"standard" deviants, er, variants, of Un*x are growing warts, er,
features. Relying on even the vendors operating system remaining the
same is probably not portable. As for the simple distinction between
BSD and SYSV, that's gone a long time ago, thanks to extensive
cross-breeding...

Then one can create configuration headers per machine -- s-machine.h,
sysdep.h, whatever, defining specific features on a per release basis,
as is sometimes necessary :-( The joys of maintaining a single source
tree for multiple architectures and OS deviants!

*Soapbox off*

#! /bin/sh -
# Fake CC driver that includes local and bsd stuff and links compatibility
# bsd routines. Also defines __iris4d__ and __irix__, as well
# as linking in /local/lib libraries before system defaults.
# Also munges output error messages from cc to BSD format, so it can
# be automatically parsed by Jove.
# Mark Moraes, University of Toronto
realcc=/usr/bin/cc
includes=
args=
for i
do
	case "$i" in
	-I*) includes="$includes $i";;
	-v) set -x;;
	esac
done
includes="$includes -I/local/include -I/usr/include/bsd"
tmp=/tmp/cc.bsd.$$
trap 'rm -f $tmp; exit $status' 0
$realcc -D__iris4d__ -D__irix__ $includes -L/local/lib "$@" -lbsd 2> $tmp
status=$?
# Postprocess errors - cc can produce stuff on stdout, for cc -M, f'rinstance
sed 's/^[^:]*: \([^:]*: \)\([^,]*\), \([^:]*: \)\(.*\)/"\2", \3\1\4/' $tmp >&2

msc@ramoth.esd.sgi.com (Mark Callow) (12/19/89)

In article <89Dec15.145750est.2273@neat.cs.toronto.edu>,
moraes@cs.toronto.edu (Mark Moraes) writes:
> 
> *Soapbox on*
> 
> It is probably much better to ifdef on specific features that one
> needs (eg.  BSD_SIGNALS, JOB_CONTROL, DIRENT, SHMEM, etc) than on a
> specific vendor type, considering the way the zillion and one
> "standard" deviants, er, variants, of Un*x are growing warts, er,
> features. Relying on even the vendors operating system remaining the
> same is probably not portable. As for the simple distinction between
> BSD and SYSV, that's gone a long time ago, thanks to extensive
> cross-breeding...
> 
> Then one can create configuration headers per machine -- s-machine.h,
> sysdep.h, whatever, defining specific features on a per release basis,
> as is sometimes necessary :-( The joys of maintaining a single source
> tree for multiple architectures and OS deviants!
> 
> *Soapbox off*

Yes, Yes,a thousand times yes.

Even though the system vendors don't define "feature ifdefs" you can write
your code as if you had them.  You simply have to create a header that does
all the ugly stuff (like that in the rest of the referenced article) and
sets the appropriate "featuredefs".

We tried to persuade the X consortium to change the ifdef's in X to a scheme
like this.  Their response was lukewarm.

yar@cs.su.oz (Ray Loyzaga) (12/21/89)

In article <2103@odin.SGI.COM> msc@sgi.com writes:
> In article <89Dec15.145750est.2273@neat.cs.toronto.edu>,
> moraes@cs.toronto.edu (Mark Moraes) writes:
> > It is probably much better to ifdef on specific features that one
> > needs (eg.  BSD_SIGNALS, JOB_CONTROL, DIRENT, SHMEM, etc) than on a
> > specific vendor type, considering the way the zillion and one
> > [Deleted]
> > Then one can create configuration headers per machine -- s-machine.h,
> > sysdep.h, whatever, defining specific features on a per release basis,
> > as is sometimes necessary :-( The joys of maintaining a single source
> > tree for multiple architectures and OS deviants!
> > 
> > *Soapbox off*
> 
> Yes, Yes,a thousand times yes.
> 
> Even though the system vendors don't define "feature ifdefs" you can write
> your code as if you had them.  You simply have to create a header that does
> all the ugly stuff (like that in the rest of the referenced article) and
> sets the appropriate "featuredefs".

> We tried to persuade the X consortium to change the ifdef's in X to a scheme
> like this.  Their response was lukewarm.

The only problem with this approach is that all the sources that you develop
will have #includes of files that are not available on any other system,
you could #ifdef the includes but on the basis of what? The bottom line
is that you need to have an "include" file that defines the way the system
is set up, and this file is sourced by cpp with every invocation.
This file should contain the "standard defines" such as mips or sysV etc,
these are currently compiled into cpp or a caller program and mean that
the user must rely on the result of the output of "strings" on cpp or cc,
and some guesswork, or hope that any changes are reflected in the
manuals on each release. I'd be much more comfortable in reading a file
such as /etc/local-system which contains
-Dmips
-DBSD4

etc, and having cpp doing something like
#!/bin/sh
/lib/cpp.real `cat /etc/local-system` "$@"

The inbuilt defines couldn't be clearer and there would be no need to
include any files that are unlikely to exist on other machines.
We currently use such a system to communicate some kernel changes
that affect the sizes of system structures to all the system
sources without having to edit them.

lamaster@ames.arc.nasa.gov (Hugh LaMaster) (12/22/89)

In article <2103@odin.SGI.COM> msc@sgi.com writes:
>In article <89Dec15.145750est.2273@neat.cs.toronto.edu>,
>Even though the system vendors don't define "feature ifdefs" you can write
>your code as if you had them.  You simply have to create a header that does
>all the ugly stuff (like that in the rest of the referenced article) and
>sets the appropriate "featuredefs".

I agree with most of what is written here, but, I sure could use a standard
way to determine from the shell what architecture of machine I am on.

I wish, for example, that the "arch" command could be made universal, and
would return a string which has 2 simple components.  For example:

sun3
sun4

decvax
decmips

sgimips

(or whatever you want, as long as it is unique).

BTW, I currently use if [] tests on files to guess,  when something
else is not available, but this doesn't work
reliably because of differences in filesystem mounts, which optional 
software is loaded, etc.


  Hugh LaMaster, m/s 233-9,  UUCP ames!lamaster
  NASA Ames Research Center  ARPA lamaster@ames.arc.nasa.gov
  Moffett Field, CA 94035     
  Phone:  (415)694-6117       

casey@gauss.llnl.gov (Casey Leedom) (12/24/89)

| From: moraes@cs.toronto.edu (Mark Moraes)
| 
| It is probably much better to ifdef on specific features that one needs
| (eg.  BSD_SIGNALS, JOB_CONTROL, DIRENT, SHMEM, etc) than on a specific
| vendor type ...

  I agree, but if you do this, please use the proposed POSIX defines for
this.  That way you shouldn't have to change too much when POSIX actually
makes it out of the shop.  (Sorry, I don't have the draft standard on me,
so I can't provide any details on what the proposed defines are or even
which file a POSIX conforming program is supposed to include to get the
set of Supported Feature Constants.)

Casey

mike@BRL.MIL (Mike Muuss) (12/30/89)

Here is the script that I use to determine the type of system
that code is compiling on.
This is an important part of the BRL-CAD Package's ability to port
between so many different UNIX systems.
	Best,
	 -Mike

-------
#!/bin/sh
#			M A C H I N E T Y P E . S H
#
# A Shell script to determine the machine architecture type,
# operating system variant (Berkeley or SysV), and
# the presence of Berkeley-style TCP networking capability.
# The machine type must be FOUR characters or less.
# 
# This is useful to permit the separation of
# incompatible binary program files, and to drive proper tailoring
# of some of the Makefiles.
#
# Note that this Shell script uses the same mechanism (ie, CPP)
# to determine the system type as the main Cakefile (Cakefile.defs)
# uses.  To support a new type of machine, the same #ifdef construction
# will be required both here and in Cakefile.defs
#
# Command args:
#	[none]	Print only machine type
#	-m	Print only machine type
#	-s	Print only system type, BRL style: (BSD, SYSV)
#	-a	Print only system type, ATT style: (BSD, ATT)
#	-n	Print only HAS_TCP variable
#	-b -v	Print all, in Bourne-Shell legible form
#
# Info note:  On a VAX-11/780, this script takes about 1.3 CPU seconds to run
#
# Mike Muuss, BRL, 10-May-1988
# With thanks to Terry Slattery and Bob Reschly for assistance
# $Revision: 9.2 $

# Ensure /bin/sh.  Make no remarks here, just do it.
export PATH || (sh $0 $*; kill $$)

FILE=/tmp/machtype$$
trap '/bin/rm -f ${FILE}; exit 1' 1 2 3 15	# Clean up temp file

/lib/cpp << EOF > ${FILE}
#line 1 "$0"

#if defined(unix) && defined(m68k)
#	undef	aux
	MACHINE=aux;
	UNIXTYPE=SYSV;
	HAS_TCP=0;
	HAS_SYMLINKS=1;
#endif

#ifdef vax
#	undef	vax
	MACHINE=vax;
	UNIXTYPE=BSD;
	HAS_TCP=1;
	HAS_SYMLINKS=1;
#endif

#ifdef alliant
#	undef	fx
	MACHINE=fx;
	UNIXTYPE=BSD;
	HAS_TCP=1;
	HAS_SYMLINKS=1;
#endif

#ifdef gould
#	undef	sel
	MACHINE=sel;
	UNIXTYPE=BSD;
	HAS_TCP=1;
	HAS_SYMLINKS=1;
#endif

#if defined(sgi) && !defined(mips)
/*	Silicon Graphics 3D */
#	undef	sgi
	MACHINE=3d;
	UNIXTYPE=SYSV;
	HAS_TCP=1;
	HAS_SYMLINKS=1;
#endif

#if defined(sgi) && defined(mips)
/*	Silicon Graphics 4D, which uses the MIPS chip */
#	undef	sgi
	MACHINE=4d;
	UNIXTYPE=SYSV;
	HAS_TCP=1;
	HAS_SYMLINKS=1;
#endif

#if defined(sun) && !defined(sparc)
#	undef	sun
#	undef	sun3
	MACHINE=sun3;
	UNIXTYPE=BSD;
	HAS_TCP=1;
	HAS_SYMLINKS=1;
#endif

#if defined(sparc)
#	undef	sun
#	undef	sun4
	MACHINE=sun4;
	UNIXTYPE=BSD;
	HAS_TCP=1;
	HAS_SYMLINKS=1;
#endif

#if defined(apollo)
#	undef	apollo
	MACHINE=apollo;
	UNIXTYPE=BSD;
	HAS_TCP=1;
	HAS_SYMLINKS=1;
#endif

#if defined(CRAY1)
/*	Cray X-M/P running UNICOS. */
#	undef	xmp
	MACHINE=xmp;
	UNIXTYPE=SYSV;
	HAS_TCP=1;
	HAS_SYMLINKS=0;
#endif

#if defined(CRAY2)
#	undef	cr2
	MACHINE=cr2;
	UNIXTYPE=SYSV;
	HAS_TCP=1;
	HAS_SYMLINKS=0;
#endif

#ifdef convex
#	undef	c1
	MACHINE=c1;
	UNIXTYPE=BSD;
	HAS_TCP=1;
	HAS_SYMLINKS=1;
#endif

#ifdef ardent
#	undef	ard
/*	The network code is not tested yet */
	MACHINE=ard;
	UNIXTYPE=SYSV;
	HAS_TCP=0;
	HAS_SYMLINKS=1;
#endif

#ifdef stellar
#	undef	stl
/*	The network code is not tested yet */
	MACHINE=stl;
	UNIXTYPE=SYSV;
	HAS_TCP=0;
	HAS_SYMLINKS=0;
#endif

#ifdef eta10
/*	ETA-10 running UNIX System V. */
/*	The network support is different enough that is isn't supported yet */
#	undef	eta
	MACHINE=eta;
	UNIXTYPE=SYSV;
	HAS_TCP=0;
	HAS_SYMLINKS=0;
#endif

#ifdef pyr
#	undef	pyr
	MACHINE=pyr;
	UNIXTYPE=BSD;	# Pyramid can be dual-environment, assume BSD
	HAS_TCP=1;
	HAS_SYMLINKS=1;
#endif

EOF

# Note that we depend on CPP's "#line" messages to be ignored as comments
# when sourced by the "." command here:
. ${FILE}
/bin/rm -f ${FILE}

# See if we learned anything by all this
if test x${MACHINE} = x
then
	echo "$0: ERROR, unable to determine machine type." 1>&2
	echo "$0: Consult installation instructions for details." 1>&2
	MACHINE=//error//
	UNIXTYPE=--error--
	HAS_TCP=0
	HAS_SYMLINKS=0
	# Performing an "exit 1" here does not help any if this script
	# is being invoked by, eg, grave accents (which is a typical use).
	# So, simply return the error strings invented above,
	# which should cause more sensible errors downstream than
	# having Shell variables competely unset.
fi

# Special cases for discriminating between different versions of
# systems from vendors.
# Try very hard to avoid putting stuff here, because this technique
# is not available for use in "Cakefile.defs", so special handling
# will be required.
#case ${MACHINE} in
#
#4d)
#	if test -d /usr/NeWS
#	then
#		# This is definitely an SGI sw Release 3.? system
#		if test ! -x /tmp/gt
#		then
#			echo 'main(){char b[50];gversion(b);printf("%2.2s\\n",b+4);exit(0);}'>/tmp/gt.c
#			cc /tmp/gt.c -lgl -o /tmp/gt
#		fi
#		case `/tmp/gt` in
#		GT)	MACHINE=4gt;;
#		PI)	MACHINE=4p;;	# Personal Iris
#		*)	MACHINE=4d;;
#		esac
#	else
#		# This is an SGI sw Release 2 system
#		MACHINE=4d2		# Unsupported
#	fi;;
#
#esac

# Now, look at first arg to determine output behavior
case x$1 in

x|x-m)
	echo ${MACHINE}; exit 0;;
x-s)
	echo ${UNIXTYPE}; exit 0;;
x-n)
	echo ${HAS_TCP}; exit 0;;
x-a)
	if test ${UNIXTYPE} = BSD
	then	echo BSD
	else	echo ATT
	fi
	exit 0;;
x-v|x-b)
	echo "MACHINE=${MACHINE}; UNIXTYPE=${UNIXTYPE}; HAS_TCP=${HAS_TCP}; HAS_SYMLINKS=${HAS_SYMLINKS}"
	exit 0;;
*)
	echo "$0:  Unknown argument $1" 1>&2; break;;
esac
exit 1