whm@megaron.UUCP (03/21/86)
I just installed C++ on our 4.3bsd VAXs and it didn't go too smoothly.
I looked through the accumulated news in this group and there seem to
be people that are running C++ on BSD systems and since there's been
no mention of any others having any trouble installing on BSD systems,
I was wondering if I managed to screw things up somehow.
The problems seemed to stem from differences in Sys5 and BSD make and sh.
For example, the instructions say to "make scratch" and issuing this
command executes the following:
cd scratch; CC=CC BSD=1 CCFLAGS="-O -DBSD"
Oops! Looks like it got the variables set ok. If it had only remembered
to do the make! We've got the BRL Sys5 package and using its make got
around the problems with BSD make. In the CC script itself, when run
with /bin/sh, you get a cryptic error about -a being an unrecognized
operator for "test". Running with Sys5 sh fixes this. Further along
in CC, the command "CC -o x x.c" eventually tries to do something like:
cc -c -o x x..c
mv x..o x.o
With BSD cc, the output file lands in "x", not x..o. With Sys5 cc, the
output goes to x..o; -o is passed on to the loader (if called).
Also, there was no man page for CC other than the one included in the hardcopy
documentation.
Am I the only person who has encountered these problems with a BSD installation?
If not, does anybody have a CC that allows the BSD cc behavior?jon@cit-vax.Caltech.Edu (Jonathan P. Leech) (03/24/86)
Summary:
Expires:
Sender:
Followup-To:
Organization : California Institute of Technology
Keywords: C++, porting, BSD, UTS, Sun, IBM
WARNING: The following is a LONG (~440 lines) message about
problems and experiences porting C++. Hit 'n' now unless you are
having problems getting the new release of C++ running.
The following is a summary of my experiences porting C++ Release
1.0 to three flavors of Unix on different hardware (VAX 11/780 4.2
BSD, Sun 2.0, IBM 4381 Amdahl UTS). Not everything said below
applies to all of the machines. I cannot promise your problems will
be the same, because I don't know how heavily the environment of our
machines (or yours) has been modified. However, this material is
accurate within these bounds and may resolve questions some people
have had about installing C++. (And, to forestall any flames, Bjarne
looked this over and approved it before I posted it).
I) Shell scripts
A) ``What's this ':' doing here?'' or, how do you get the right shell?
Different versions of Unix have different conventions for
identifing shell scripts. Unfortunately it appears to be
impossible to come up with a single Bourne Shell script file which
can be used with impunity on all Unix variants. Here's my summary
of how systems deal with scripts:
4.2 BSD (VAX)
Apparently all scripts are executed with sh UNLESS there
is a line of the form '#!program' where 'program' is the
alternative interpreter (such as /bin/csh) to run. No
problems with the supplied scripts here.
4.2 BSD (Sun release 2.0)
Apparently the default here is csh, not sh (my login shell
is csh, which may be the cause) . There is in fact a line of
the form '#!/bin/sh' in the 'CC' shell script, but it's on
the SECOND line, so it's not recognized. It must be moved to
the first line. The 'bsd.sed' shell script (if there's
occasion to run it) must have the '#!/bin/sh' line added as
the first line.
Amdahl UTS
In order to get a script executed by sh on this variant,
it needs to have a ':' as the first character of the file (or
at least this suffices). Even '#!/bin/sh' as the first line
does not do the desired thing. So CC must be edited to add
this.
B) Nobody bothered to test `test'.
There is a problem with the 'CC' shell script on many Unix
systems. The 'test' program is used in CC in the following
context (towards the end of the script):
if test "$R" -a ! "$PLUSI"
then
rm $C
fi
unfortunately, strings as operands to 'test' do not work quite
right on (at least) 4.2 BSD derived systems. In theory, an empty
string "" should be equivalent to '0' or 'false' and the converse
for a non-empty string. In fact this only works if the ONLY
argument to test is a SINGLE empty (or not) string. To observe
this, execute
test "" -a ""
on a 4.2 system and cringe. This behavior has been seen on VAX/4.2
BSD, Sun 4.2 BSD, VAX/4.3 BSD, and a version of Unix derived from
Unix/TS and Unix/32V. Test appears to work properly on all the
System III/System V Unixes (Unices? Unixi?) that I have access to.
To correct this problem, change the 4 lines above to
if test "$R" ; then
if test ! "$PLUSI" ; then
rm $C
fi
fi
this is a bit more verbose, but works.
C) But... how do you find the members?
The source to cfront (the compiler portion of C++) comes in
both C++ and C form, the latter to provide a way of bootstrapping
cfront. The C version of cfront appears to be targeted for a
System V Unix. In order to get cfront working properly on a 4.2
BSD system (in fact on any Unix system), the declaration of the
'FILE' aka '_iobuf' structure must be changed to correspond with
with that on your system. Otherwise cfront will explode the first
time it tries to do I/O.
There is a supplied shell script 'bsd.sed' in the 'scratch'
directory which is supposed to massage the C source to cfront by
changing the declarations of FILE members. Unfortunately, it does
not do the complete job; the '__iobuf__flag' member of FILE is a
SHORT on 4.2 BSD, not a char. This might (or might not) make a
difference, depending on the byte order and alignment constraints
of the machine cfront is being compiled on. The following shell
script corrects the declaration of FILE; it should be run in the
'scratch' directory AFTER bsd.sed.
#!/bin/sh
#ident "@(#)cfront:scratch/bsd42.sed (jon@csvax.caltech.edu) 1.0"
echo "Fixing _iobuf structures for 4.2 BSD (__iobuf__flag member):"
for f in */*..c
do
echo $f
sed -e '/__iobuf__flag/s/char/short/' $f > temp$$
mv temp$$ $f
done
echo "We now return to our regularly scheduled C++ installation process"
II) OS/utility bugs
A) exit() vs. return() or, ``I don't CARE what you said! I'm
exiting successfully anyway!''
The 'CC' script uses the exit status of the program 'munch' to
determine if another pass of the loader needs to be made to
properly call static constructors and destructors. Munch tries to
return this status by just doing 'return 0' or 'return 1' from
main(). Unfortunately, on several Unix variants (at least Sun 4.2
BSD and Amdahl UTS), ANY successful return from main causes an
exit status of 0 instead of the returned value. For portability,
change all 'return n' to 'exit(n)' in main() of
lib/static/munch.c.
B) Optimization
On UTS, the optimizer pass of the C compiler (/lib/c2) core
dumps while trying to compile parts of the C++ library
(specifically lib/complex/io.c). Rather than try to figure out
why, I just removed the -O flag from 'lib/mk/makefile' and
'makefile'. Bjarne says that many optimizers break on
automagically generated C code such as that produced by cfront.
C) Makefiles
i) UTS
Some parts of the supplied makefiles contain Bourne shell
constructs. On UTS, the underlying shell that is invoked by
'make' is normally /bin/sh, but if the environment variable
'SHELL' is defined, that is used instead. If your login shell is
NOT sh (say /usr/ucb/csh instead like mine), make will die when
it feeds sh commands to a csh. Here are 2 solutions:
(i) define SHELL=/bin/sh in the environment
(ii) Add a line of the form 'MAKE=/bin/make SHELL=' to the
top-level makefile. This will cause SHELL to be undefined
when lib/mk/makefile is invoked, so sh will be used as
desired. This is the preferred solution.
ii) BSD
When the top-level makefile invokes other makefiles, it uses
the construct $(MAKE). Unfortunately, MAKE is NOT a predefined
make variable in the 4.2 BSD implementation. To correct this, add
a line of the form
MAKE=/bin/make
at the start of the top-level makefile.
D) Ranlib (BSD)
When an archive library (such as the libC.a created in the
bootstrapping process) is copied, BSD systems sense the new
modification date and complain that 'ranlib' has not been run on
the archive since the copy. Ld will then exit with an unwarranted
error code, which causes 'CC' to bomb out early. To correct this,
once libC.a is installed in its final destination (/lib, /usr/lib,
or whatever), re-run 'ranlib' on it.
E) Dereferencing NULL
This fix has been seen before but I'm putting it in for completeness.
Make the following change in src/print.c:
diff print.c.new print.c.orig
1452,1453c1452
< if ( (e2->tp == 0) ||
< Pptr(t1)->typ != Pptr(e2->tp)->typ) {
---
> if (Pptr(t1)->typ != Pptr(e2->tp)->typ) {
III) Random comments on porting C++ to different target machines
A) Portability of the supplied C code to cfront
As the AT&T installation guide briefly mentions, the
declarations of the stdio FILE structure must be correct for the
target system. That is not the only problem, however. Cfront
needs to know about size and alignments of data types on the
target architecture in order to generate correct C code for said
machine. WARNING: the supplied C code for cfront is only promised
to work on a 3B or VAX because of this.
The only way to get around this is to first get cfront
running on one of the machines the C code WILL work on, then
cross-compile cfront (using an appropriate size/alignment file)
for the target machine. Then you must move to the target machine
and restart the process from 'scratch' (so to speak).
B) Cross-compiling
This assumes that you already have a working version of CC on
some machine. If you don't, find some friendly person with a VAX
or 3B.
First, you have to find an appropriate size/alignment file for
the target machine. Here are size/align files for Sun 2 (68000)
and Amdahl UTS (IBM 370 architecture):
Sun:
char 1 1
short 2 2
int 4 2 2147483647
long 4 2
float 4 2
double 8 2
bit 8 32
struct 2 2
frame 2 2
top 0 0
word 4 0
wptr 4 2
bptr 4 2
UTS:
char 1 1
short 2 2
int 4 4 2147483647
long 4 4
float 4 4
double 8 8
bptr 4 4
wptr 4 4
struct 1 1
ptr 4 4
bit 8 32
word 4 0
In addition, you may need to modify the 'DF_SENSITIVE' #define
in src/size.h; I believe this should be 0 for Suns and 1 for UTS.
Next, modify the 'fillscratch' entry in the makefile so that
the invocations of CC include a '+xfile' where 'file' is the
size/alignment file above. Here's how I did it for UTS (working
from a VAX). I actually added a new target here:
# This makes port files for UTS
# UTS size/alignment file
UTSDIR=/usr/src/c++/CC/UTS
UAL=$(UTSDIR)/uts_size_align
utsport:
make sure the directories exist:
if test ! -d uts/src; then mkdir uts/src; fi
if test ! -d uts/mnch; then mkdir uts/mnch; fi
if test ! -d uts/lib; then mkdir uts/lib; fi
cd src; yacc gram.y
cd uts/src; $(CC) +x$(UAL) -I$(UTSDIR) -I../../src -I../../incl \
-Fc -..c ../../src/*.c;
cd uts/lib; $(CC) +x$(UAL) -I$(UTSDIR) -I../../lib/complex \
-I../../incl -Fc -..c ../../lib/new/*.c
cd uts/lib; $(CC) +x$(UAL) -I$(UTSDIR) -I../../lib/complex \
-I../../incl -Fc -..c ../../lib/static/*.c
rm uts/lib/munch..c
#Dont need a real munch here:
echo "main(){ exit(0); }" >uts/mnch/munch..c
in the above segment of makefile, UTSDIR is the location of a
directory containing
(i) The size_alignment file (which is defined on the next
line)
(ii) /usr/include/stdio.h and /usr/include/ctype.h from the
target machine. It is VITAL that these be included instead
of the versions of stdio.h and ctype.h in the incl/
directory.
Make a directory 'uts' and invoke 'make utsport'. When
finished, uts/... will contain C code suitable for compiling
under UTS.
At this point, move the directory tree 'uts/...' from the host
machine to the target. Move it into 'scratch/...' instead of
'uts/...' on the target, and proceed with the bootstrapping
process.
IMPORTANT NOTE: the generated cfront on the target machine
will STILL require you to explicitly use the
'+xsize_alignment_file' for the target because, despite the fact
that it was itself compiled correctly, the default size/alignments
built in are those for a vax. Two ways to work around this:
(i) Modify the 'CC' script to ALWAYS use +x (putting the file
in some publicly accessible place, probably the same
directory as CC itself).
(ii) Modify the file 'src/size.h' to contain the correct
size/alignments for your target, then recompile cfront
from the C++ source (again, using the +x option). The
cfront which is generated will now have the correct
size/alignments built in. It is also a good
confidence-building measure for cfront to be able to
successfully recompile itself on the target machine. This
is my preferred solution.
The include files installed in /usr/include/CC (or wherever)
must be correct for the target. This could require a substantial
amount of editing. 'incl/ctype.h' should be replaced with that
from the target system's /usr/include. 'incl/stdio.h' should also
be replaced; however, you must add the correct function prototypes
for your system to stdio.h, or cfront cannot be recompiled
successfully. The problem is that most stdio.h files have
declarations of the form
extern int setbuf();
unfortunately, C++ will interpret this as 'setbuf takes NO
arguments'. When it then encounters an actual call to setbuf
(containing 2 arguments), an error occurs. Since such calls
appear in the source to cfront itself, it cannot be successfully
recompiled without adding the function prototypes to CC's stdio.h.
C) Compiling the library libC.a (in lib/*/*)
When compiling the full libC.a, you must change 'incl/math.h'
(which should become '/usr/include/CC/math.h') to include a
correct definition of 'MAXFLOAT' for your system. Look in
'/usr/include/math.h' for MAXFLOAT or HUGE (probably labelled
appropriately). There are other conditional definitions of this
nature in the CC include files, but they don't seem to affect
compiling cfront and libC.
I found that for some reason (probably a shell or make bug),
the following changes had to be made in lib/mk/makefile for the
Suns:
OLD:
OFILES = $(O_COMPLEX) $(O_GENERIC) $(O_NEW) \
$(O_STATIC) $(O_STREAM) $(O_TASK)
NEW:
OFILES = $(O_COMPLEX) $(O_GENERIC) $(O_NEW) \
$(O_STATIC) $(O_STREAM)
OLD:
libC.a: $(O_COMPLEX) $(O_GENERIC) $(O_NEW) $(O_STATIC) $(O_STREAM) Task
NEW:
libC.a: $(O_COMPLEX) $(O_GENERIC) $(O_NEW) $(O_STATIC) $(O_STREAM)
The problem was that the shell code executed in the 'Task'
target was failing for some reason, and causing make to die. Since
the task library is not supported on Suns anyway, there is no loss
from doing this.
D) Testing
Getting cfront to recompile itself is certainly a good test.
The only other test I have come up with is this progam:
#include <stream.h>
main() {
cout << "Hello, world\n";
}
What makes this worth doing is that 'cout' has a static
constructor; thus, if the 'munch' program does not work properly,
said constructor will not be initialized and when the program is
run you will probably get a core dump (dies in
__ostream__lshiftFPC__) instead of 'Hello, world'.
E) From the author
The following comments were sent to me by Bjarne as I was
trying to get C++ up ; there is some overlap with the above but
they may be more comprehensible than mine.
> I will brifly explain the porting process here. Cfront is a compiler front-end,
> not a simple pre-processor, in particular it has to know about the target machine
> in order to calculate sizeofs. What you get on the tape is a C version for a VAX
> or a 3B. To run cfront on a different machine you must port, not merely re-compile.
>
> When you port, the key step is to create a new set of C source files like the ones
> you received for a VAX. This you do by compiling the C++ source files using
>
> (1) header files <stdio.h> and <ctype.h> from the target machine (using
> the -I directive) so that the system dependencies are hanled correctly.
> (2) a size/align file for the target machine (using the +x directive) so
> that cfront agrees with the target machine as to the sizes of objects.
>
> (here is the source of your problem with expr..c - the sizes has been
> calculated wrongly using VAX sizes on a SUN and the free store is
> messed up).
>
> Here is a size/align file for a Sun:
[ Given above ]
> Assuming you call it ``szal'' and put it in directory SUN (where I have also
> assumed that stdio.h and ctype.h is stored) you can make a ..c file like this:
>
> CC -F -ISUN +xSUN/szal main.c | sed /^#/d > main..c
>
> Don't worry about SZ_TOP and AL_TOP, they are not really used.
>
> With that done you can simply compile and install munch.c and the libraries on
> the terget machine using the new cfront.
>
> This is of course not as easy as porting a simple machine independent C program,
> but not too bad for a compile port. Think of CC as a two pass compiler using a
> particularly readable and portable intermediate form (seen this way cc is the
> fabled ``machine independent assembler'' or ``universal intermediate form'' -
> UNCOL).
>
> - Bjarne
Jon Leech (jon@csvax.caltech.edu || ...seismo!cit-vax!jon)
Caltech Computer Science Graphics Group
__@/olson@batcomputer.TN.CORNELL.EDU (Todd Olson) (03/24/86)
In article <952@megaron.UUCP> whm@megaron.UUCP writes: >I just installed C++ on our 4.3bsd VAXs and it didn't go too smoothly. Yes, indeed. I've been thinking about posting a similar article about the problems of bring C++ under bsd4.2 and asking for assistance. I have experienced every problem you have, and since I'm not too experienced in bring things up I have been stumbling all over the place. Maybe some of the wiser 4.2 types with interest in C++ could be pursuaded to make available a better make file (maybe it could go on the distribution tape) (I guess I have been spoiled by all the fine work the UW people did in making TeX available for bsd4.*) Thanks for your note, it will help me. If I ever get my C++ up I'll post my experiences Todd Olson ARPA: olson@lasspvax -- or -- olson%lasspvax.tn.cornell.edu@cu-arpa UUCP: {ihnp4,allegra,...}!cornell!lasspvax!olson US Mail: Dept Physics, Clark Hall, Cornell University, Ithaca, New York 14853-2501 -- Todd Olson ARPA: olson@lasspvax -- or -- olson%lasspvax.tn.cornell.edu@cu-arpa UUCP: {ihnp4,allegra,...}!cornell!lasspvax!olson US Mail: Dept Physics, Clark Hall, Cornell University, Ithaca, New York 14853-2501
mat@mtx5a.UUCP (m.terribile) (04/03/86)
> WARNING: The following is a LONG (~440 lines) message about > problems and experiences porting C++. Hit 'n' now unless you are > having problems getting the new release of C++ running. . . . > B) Optimization > > On UTS, the optimizer pass of the C compiler (/lib/c2) core > dumps while trying to compile parts of the C++ library > (specifically lib/complex/io.c). Rather than try to figure out > why, I just removed the -O flag from 'lib/mk/makefile' and > 'makefile'. Bjarne says that many optimizers break on > automagically generated C code such as that produced by cfront. I can understand why compilers might have difficulty. On the other hand, it is precisely on automagically generated code that optimization is most needed, because such code is most likely to have extra copy and conversion operations introduced by the crypto-automagicalator (eg. cfront :-) Those of us who are in a postion to influence such things should push for robust compilers and optimizers; Maytags, if you will, that can take lots of use and come up for more. > Getting cfront to recompile itself is certainly a good test. > > The only other test I have come up with is this progam: > > #include <stream.h> > main() { > cout << "Hello, world\n"; > } > > What makes this worth doing is that 'cout' has a static > constructor; thus, if the 'munch' program does not work properly, > said constructor will not be initialized and when the program is > run you will probably get a core dump (dies in > __ostream__lshiftFPC__) instead of 'Hello, world'. Ah, yes. For those of you who have the ``patch'' version instead of the ``munch'' version, if this error occurs, check the symbols in the source code for ``patch''. You may find that your cc puts in more or fewer underscores than patch expects. There are two or three lines that need to be changed, and the code is surprisingly simple. I have the patch version up here, and it seems to run fine. -- from Mole End Mark Terribile (scrape .. dig ) mtx5b!mat (Please mail to mtx5b!mat, NOT mtx5a! mat, or to mtx5a!mtx5b!mat) ,.. .,, ,,, ..,***_*.