guy@sun.UUCP (05/05/86)
> The "proper" way to do this is by testing `uname -m`. Well, "uname" isn't on all machines, so it's only the proper way on S5 (not V7, 4BSD, or S3). Besides, as you point out, there are no standards on what "uname -m" should return. One problem here is that on my machine, for instance, there are *four* different possible answers: 1) it has a Motorola 68000-family chip as its CPU, so it should be something like "m68k"; 2) it has a Motorola 68020 as its CPU, so it should be something like "M68020"; 3) it is a Sun, so it should be something like "sun"; 4) it is a Sun-3, so it should be something like "sun-3". As such, unless AT&T-IS is going to change the layout of the "uname" structure to include several more fields (which is extremely unlikely), "uname" isn't the right answer. Furthermore, the Makefile for VAX S5R2 sets things up so that "uname -m" returns "vax-780"; the equivalent on my machine would be to have it return "sun-3/50". However, everything after the "vax" in "vax-780", and everything after the "3" in "sun-3/50", is of minimal interest to 99 44/100% of the software out there (the kernel cares, but it can figure out the complete machine type at boot time). The version of the C preprocessor that comes with the Fourth Generation Make ("nmake" from the AT&T Toolchest) has some functions for these purposes. They have "model", "architecture", and "machine". "model" Defines the hardware model or workstation name. Example values for "model-name" are "apollo", "sun", "ibm-pc" and "unix-pc". "architecture" Defines the processor architecture name. Example values for "architecture-name" are "3b", "68000", "ibm", "pdp11", and "vax". "machine" Defines the processor architecture version. Example values for "architecture-version" are "2, "20", and "20s" for "architecture(3b)", "70" etc. for "architecture(pdp11)", and "750", "780", and "micro" for "architecture(vax)". I could see the following categories: CPU family - general family of CPUs. "pdp11", "vax", "m68k", "NS32000", etc. (unfortunately, "iAPX86" is, I think, somehow equivalent to "8086"; some name is needed for the 8086, 8088, 80186, 80188, 80286, 80386, ...). CPU family member - "M68010", "M68020", "iAPX286", etc. Machine family (which would be the same as the CPU family in most cases of proprietary architectures) - "pdp11", "vax", "sun", "apollo", "power5", "power6", etc.. Machine sub-family - "sun2", "sun3", etc.. I'm not sure whether this is necessary or not. The "sun2"/"sun3" example might not make it necessary; one could treat "sun2" and "sun3" as separate "machine families" and do anything Sun-dependent if it's "sun2" or "sun3". Specific machine - "pdp11/74", "vax-780", etc.. If this is useful at all, it might be subsumed under "CPU sub-family". Unfortunately, the AT&T 3B machines really throw a bit of a monkey wrench into this. The 3B1 has a Motorola 68010 chip; the 3B<n>, for <n> != 20, have a WE32000 series chip; the 3B20 has a proprietary CPU which is close to the WE32k at the assembly-language level, but not at the machine-language level. I'm sure other systems create similar pathologies. In some cases, this stuff is used to identify peculiarities of the UNIX implementation, rather than of the machine. If this would complicate any of this, the answer is to take another leaf from that "cpp"s book and have a separate command to indicate the particular flavor of UNIX. This, of course, has its own complications; do you just identify the general UNIX family (if so, what is the S5-based Xenix? Is it "xenix-5" or whatever Microsoft calls it, or is it "system5", or what? What about a system which offers both 4BSD and S5 features?), or do you identify the system by what the vendor calls it (in which case, it's a pain to construct predicates which say "where are mailboxes kept" or "does this have S5 IPC" or...). > N.B. The same machine type should be pre#defined by CPP. I sort of agree, except that pre#defining names causes all sorts of problems; in effect, arbitrary portions of your name space can be hijacked by vendors in the future. The "function" approach of the Fourth Generation Make's "cpp" seems better; you say #if architecture(vax) instead of #if vax If there is a function of this sort named "foo", there should be a command "foo" such that if the function "foo(X)" is true, the "foo" command should print "X" on its standard output. Of course, one reason for using these #defines is to ask questions like "what's the byte order on this machine"; using these #defines is a pain because your code won't be prepared to deal with arbitrary new machines. It might be better to define something like "BIG_ENDIAN" or "LITTLE_ENDIAN" in some standard #include file, and insist that vendors put this into their standard copy of this #include file. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.arpa
gwyn@brl-smoke.ARPA (Doug Gwyn ) (05/06/86)
Greg and Guy have made some good points. I agree that the current situation is inadequate in general; there is NO good universal way to determine target system specifics at "make" or compile time. This makes it even more important to avoid system dependencies in code that is targeted to be used on a variety of systems. There are some cases where one simply has to take machine architecture into account, but the vast majority of such applications need not do so, and many others can be structured so that system-specific code is limited to a small handful of common interface modules. This approach, coupled with widespread adoption of language and environment standards, makes porting much less painful than usual.