jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) (10/22/90)
Hi - We have a library written in Fortran77 which includes a block data subroutine. If we use "ar" to archive the object files of the library, and then try to compile a program using the resulting "lib???.a" file, everything works fine EXCEPT the block data subroutine is never executed (that is, the initializations are not made). If the block data object file is linked in explicitly with the fortran compiler, then the initializations are done. Archiving the block data subroutine does work elsewhere (at least on computers running BSD4.3). It does not work on our SGI Personal Iris, (running IRIX version 3.2 I believe - but am not positive... I can find out if it makes a difference). Is this a problem with SGI's archiver, or archivers on machines running System V-like operating systems in general? We do not have a "ranlib" program on the SGI; the "ar" program creates the symbol tables that the loader needs (we can call normal subroutines that have been archived and it works fine). Thanks, Jeff -- /****************************************************************************** ** Jeff Biesiadecki ** University of Illinois, Urbana-Champaign ** ** jeffb@aquifer.las.uiuc.edu ** Departments of Geology and Computer Science ** ******************************************************************************/
burley@world.std.com (James C Burley) (10/22/90)
In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes:
Hi -
We have a library written in Fortran77 which includes a block data
subroutine. If we use "ar" to archive the object files of the library,
and then try to compile a program using the resulting "lib???.a" file,
everything works fine EXCEPT the block data subroutine is never executed
(that is, the initializations are not made). If the block data object file
is linked in explicitly with the fortran compiler, then the initializations
are done.
Hi back! I know nothing about "ar" or "lib???.a" files. But in Fortran,
there is a specification for forcing the inclusion of a BLOCK DATA program
unit in a program. It is EXTERNAL, believe it or not. For example:
PROGRAM FOO
EXTERNAL BDATA
COMMON /X/I
PRINT *,I
END
BLOCK DATA BDATA
COMMON /X/I
DATA I/5/
END
Without "EXTERNAL BDATA", the block data program unit must be explicitly
linked with the program, or whatever wording to that affect is appropriate
(since the standard doesn't really talk about linking). With it, the linker
should complain if it can't find a block data program unit named BDATA when
linking FOO, and thus should also pull it in from any library it is
searching.
Give this approach a try. I realize it requires you to modify the code
using the block data program unit, but that might be a good idea anyway, to
improve its portability. However, be aware that some nonconforming
implementations of Fortran might do the wrong thing, like assume BDATA must
be a subroutine or function but NOT a block data program unit, so try testing
this approach using, say, the example above (i.e. put BDATA in a library using
"ar" and link it to FOO after compiling both).
James Craig Burley, Software Craftsperson burley@world.std.com
silvert@cs.dal.ca (Bill Silvert) (10/22/90)
In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes: >We have a library written in Fortran77 which includes a block data >subroutine. If we use "ar" to archive the object files of the library, >and then try to compile a program using the resulting "lib???.a" file, >everything works fine EXCEPT the block data subroutine is never executed >(that is, the initializations are not made). If the block data object file >is linked in explicitly with the fortran compiler, then the initializations >are done. This is a common (:)) problem which arises from the fact that the linker looks only for subroutines that are called, and since block data is not called, it doesn't get linked. One sure fix is to combine the block data unit with a subroutine in one file, since the entire file with both units will then get loaded if the subroutine is called. -- William Silvert, Habitat Ecology Division, Bedford Inst. of Oceanography P. O. Box 1006, Dartmouth, Nova Scotia, CANADA B2Y 4A2. Tel. (902)426-1577 UUCP=..!{uunet|watmath}!dalcs!biomel!bill BITNET=bill%biomel%dalcs@dalac InterNet=bill%biomel@cs.dal.ca
ddh@hare.cdc.com (Dan Horsfall) (10/22/90)
In article <BURLEY.90Oct22050633@world.std.com> burley@world.std.com (James C Burley) writes: > In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes: > > We have a library written in Fortran77 which includes a block data > subroutine. If we use "ar" to archive the object files of the library, > and then try to compile a program using the resulting "lib???.a" file, > everything works fine EXCEPT the block data subroutine is never executed > (that is, the initializations are not made). If the block data object file > is linked in explicitly with the fortran compiler, then the initializations > are done. > Keep in mind here a terminology issue: block data subprograms are not executable. They by definition contain no executable code. They cannot be "called". > Hi back! I know nothing about "ar" or "lib???.a" files. But in Fortran, > there is a specification for forcing the inclusion of a BLOCK DATA program > unit in a program. It is EXTERNAL, believe it or not. For example: > > PROGRAM FOO > EXTERNAL BDATA > COMMON /X/I > PRINT *,I > END > > BLOCK DATA BDATA > COMMON /X/I > DATA I/5/ > END > > Without "EXTERNAL BDATA", the block data program unit must be explicitly > linked with the program, or whatever wording to that affect is appropriate > (since the standard doesn't really talk about linking). With it, the linker > should complain if it can't find a block data program unit named BDATA when > linking FOO, and thus should also pull it in from any library it is > searching. > I beg to differ. EXTERNAL for linking in block data routines is a "fairly common" extension, but is NOT standard. Here's the problem at the loader level: Block data subprograms contain no executable code. Thus, they do not contain an entry point. A while back, some compiler writers figured out that if they added an entry point to a block data routine (which actually makes it executable, tho usually the supporting code is an instant _return). Now, having an entry point makes it resolvable by other routines that declare the same symbol as an external reference. How to do this in a manner that doesn't actually execute the code? Declare the symbol EXTERNAL in some other routine. Not all vendors support this mechanism, but this doesn't mean they are nonconforming. MIPS is one of these; mips makes the sgi box; James Burley's otherwise exemplary solution doesn't apply to you. What you gotta do is force load your block data routines the same way you force load your main program to start the loading process, e.g.: f77 -o xxx main.o bdata.o libx.a ( In our case here, we use f77 -o xxx *.o *.a, and make sure that the right *.o's are available. Kludge, but the only solution.) -- Horse + Control Data Corporation Dan Horsfall +1-612-482-4622 + 4201 Lexington Ave North Internet ddh@dash.udev.cdc.com + Arden Hills MN 55126 USA
doog@travis.ssd.csd.harris.com (Doug Scofield) (10/22/90)
)From article <>, by burley@world.std.com (James C Burley):
)) In article <> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes:
))
)) [ user wishes linker to pull block data from library ]
)
) [ suggests using the EXTERNAL keyword to cause an external reference, ]
) [ which would in theory include the block data subprogram ]
)
) ... However, be aware that some nonconforming
) implementations of Fortran might do the wrong thing ...
Actually, implementations may do whatever they want in this case.
Block data subprogram names are defined to be global to the
execution unit (16.1), and block data names are allowed in EXTERNAL
statements (8.7), but no functional use is described. In fact, this
is explicitly stated in (B16):
The name of a block data subprogram has no explicit use within
the FORTRAN language. It is available for documentation and
for possible use within a computer environment.
This "possible use" would include what you require. An innocuous
global definition of the block data name would be required in the
block data object, and a global reference would be generated within
the source object. Some vendors may be hesitant to do the latter,
as it requires generating a dummy reference for every unused
EXTERNAL name.
--
doug scofield doog@ssd.csd.harris.com (preferred)
harris computer systems uunet!hcx1!doog
system@alchemy.chem.utoronto.ca (System Admin (Mike Peterson)) (10/23/90)
In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu> jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes: >We have a library written in Fortran77 which includes a block data >subroutine. If we use "ar" to archive the object files of the library, >and then try to compile a program using the resulting "lib???.a" file, >everything works fine EXCEPT the block data subroutine is never executed >(that is, the initializations are not made). ... You can make this work properly on most normal systems (Sun, DEC/Ultrix, Cray/UNICOS, IBM RS/6000, SGI) by: - giving the BLOCK DATA routine a unique name. - putting an 'EXTERNAL blockdataname' statement in the subroutine(s) that want the COMMON block to be loaded. Note that this technique will NOT work reliably on Apollo systems :-(. -- Mike Peterson, System Administrator, U/Toronto Department of Chemistry E-mail: system@alchemy.chem.utoronto.ca Tel: (416) 978-7094 Fax: (416) 978-8775
vjs@rhyolite.wpd.sgi.com (Vernon Schryver) (10/23/90)
In article <27320@shamash.cdc.com>, ddh@hare.cdc.com (Dan Horsfall) writes: > ... mips makes the sgi box ... > Horse > + Control Data Corporation > Dan Horsfall +1-612-482-4622 + 4201 Lexington Ave North > Internet ddh@dash.udev.cdc.com + Arden Hills MN 55126 USA The preceding was probably a typo, but ... MIPS does not make IRIS's. Silicon Graphics Computer Systems, Inc. makes IRIS's. MIPS makes their own boxes. I'm not even sure which of the several silicon foundaries SGI is using for the MIPS R3000 that is probably in whichever SGI box is being mentioned. I don't think MIPS is in the silicon business any more. I think it's been years since any IRIS contained any hardware manufactured by MIPS. It is or at least has been true that packing cases leave Mtn.View loading docks with labels that do not mention SGI but do say "Cyber". It is true SGI ships modified versions of MIPS compilers for some but not all languages. MIPS &co. are great guys with good machines and all that, but everyone working at SGI knows they are not as great as SGI. Vernon Schryver, vjs@sgi.com
milind@agni.cc.nd.edu (Milind Saraph) (10/23/90)
|> |>Hi - |> |>(stuff deleted) |> |>Archiving the block data subroutine does work elsewhere (at least on computers |>running BSD4.3). It does not work on our SGI Personal Iris, (running |>IRIX version 3.2 I believe - but am not positive... I can find out if it |>makes a difference). |> |>Is this a problem with SGI's archiver, or archivers on machines running |>System V-like operating systems in general? We do not have a "ranlib" |>program on the SGI; the "ar" program creates the symbol tables that the |>loader needs (we can call normal subroutines that have been archived and |>it works fine). |> |>Thanks, |>Jeff |> |>-- |>/********************************************************************* ********** |>** Jeff Biesiadecki ** University of Illinois, Urbana-Champaign ** |>** jeffb@aquifer.las.uiuc.edu ** Departments of Geology and Computer Science ** |>********************************************************************** *********/ This has certainly been a problem on Stellar and Ardent machines (SYS-V like OS). -- milind
dik@cwi.nl (Dik T. Winter) (10/23/90)
In article <1990Oct22.130143.29775@cs.dal.ca> bill%biomel@cs.dal.ca writes: > One sure fix is to combine the block > data unit with a subroutine in one file, since the entire file with > both units will then get loaded if the subroutine is called. Probably sure within this context (Unix systems). Certainly not sure in general. I know of at least one (non Unix) system where this will fail. In short: there is no solution that will work everywhere, except explicitly loading the block data subprogram. -- dik t. winter, cwi, amsterdam, nederland dik@cwi.nl
sjc@key.COM (Steve Correll) (10/26/90)
In article <1990Oct22.033107.5159@ux1.cso.uiuc.edu>, jeffb@aquifer.las.uiuc.edu (Jeffrey Biesiadecki) writes: > We have a library written in Fortran77 which includes a block data > subroutine. If we use "ar" to archive the object files of the library, > and then try to compile a program using the resulting "lib???.a" file, > everything works fine EXCEPT the block data subroutine is never executed >... > Is this a problem with SGI's archiver, or archivers on machines running > System V-like operating systems in general? Yes, most Unix System V Release 3 linkers behave differently than most BSD4.3 linkers, in a fashion that is sufficient to explain your problem. Suppose there is a .o file in the archive library which does not define any symbol which the linker has seen previously, except for one: an uninitialized common block. Should the linker bind that .o file into the program on the basis of that common block alone, even though the .o file does not affect the meaning of that common block? Most BSD linkers answer "yes" and most SVR3 linkers answer "no". The answer _can_ affect the meaning of the program. To sidestep arguments about the Fortran standard for the moment, consider (sorry) a C example: file main.c: int c; /* Think of this as uninitialized common */ main() { return com1(); } file com1.c: int c; /* Think of this as uninitialized common */ int d = 5; /* Think of this as initialized common */ com1() { return c + d; } file com2.c: int c = 6; /* Think of this as initialized common within blockdata */ Now do the following in /bin/sh: cc -c main.c cc -c com1.c cc -c com2.c ar cr lx.a com1.o com2.o cc -o main main.o lx.a ./main echo $? Most BSD systems will print "11" and most SVR3 systems will print "5" (because uninitialized common is 0 on Unix systems). If you say: nm main on most BSD systems, both "c" and "d" will have storage class "DATA", indicating that they have been initialized because com2.o was bound. On most SVR3 systems, "c" will have storage class "BSS", indicating that it is uninitialized because com2.o was not bound. Now as for arguments about the Fortran 77 standard: James Craig Burley writes: > ...I believe if you look into > the history of the F77 standard, you'll find that the reason Page 8-9 lines 30 > and 31 allow block data subprogram names in the EXTERNAL statement was to > accommodate systems allowing linking of libraries that needed a means to > allow procedures in a library to specify that they also needed a corresponding > BLOCK DATA program unit from that same library. > ...It stands to reason, therefore, that anyone designing a new Fortran system > and wishing to be standard-conforming would support both the letter and the > spirit of the standard...any responsible developer would interpret it that > way... I am acquainted with language-independent compiler optimizers which delete unreferenced global imports, causing EXTERNAL BDATA to vanish without a trace. Perhaps you are not accustomed to such aggressive optimization. Clearly it's a matter of taste, but around here we tend to regard complaints about such deletions with the same sympathy we extend to complaints about our not allocating unSAVEd local variables in memory: if the standard doesn't say you can rely on it, please don't. Consider that the Fortran 77 standard says (2.12) that when a procedure _reference_ is _executed_, the procedure must be "available" (the Fortran 77 circumlocution to avoid talking about "linking"). Can anyone find a provision in the standard which says that the appearance of a procedure name in an EXTERNAL statement requires the procedure to be "available"? I can't. In its absence, I can imagine a perverse user arguing that the following program is standard-conforming even if X is not available: EXTERNAL X END and complaining that a processor which refuses to construct an executable program in the absence of X fails to conform to Fortran 77! -- sjc@key.com or ...{sun,pyramid}!pacbell!key!sjc Steve Correll
burley@world.std.com (James C Burley) (10/26/90)
In article <2208@key.COM> sjc@key.COM (Steve Correll) writes: James Craig Burley writes: > ...I believe if you look into > the history of the F77 standard, you'll find that the reason Page 8-9 lines 30 > and 31 allow block data subprogram names in the EXTERNAL statement was to > accommodate systems allowing linking of libraries that needed a means to > allow procedures in a library to specify that they also needed a corresponding > BLOCK DATA program unit from that same library. > ...It stands to reason, therefore, that anyone designing a new Fortran system > and wishing to be standard-conforming would support both the letter and the > spirit of the standard...any responsible developer would interpret it that > way... I am acquainted with language-independent compiler optimizers which delete unreferenced global imports, causing EXTERNAL BDATA to vanish without a trace. Perhaps you are not accustomed to such aggressive optimization. Clearly it's a matter of taste, but around here we tend to regard complaints about such deletions with the same sympathy we extend to complaints about our not allocating unSAVEd local variables in memory: if the standard doesn't say you can rely on it, please don't. Consider that the Fortran 77 standard says (2.12) that when a procedure _reference_ is _executed_, the procedure must be "available" (the Fortran 77 circumlocution to avoid talking about "linking"). Can anyone find a provision in the standard which says that the appearance of a procedure name in an EXTERNAL statement requires the procedure to be "available"? I can't. In its absence, I can imagine a perverse user arguing that the following program is standard-conforming even if X is not available: EXTERNAL X END and complaining that a processor which refuses to construct an executable program in the absence of X fails to conform to Fortran 77! -- sjc@key.com or ...{sun,pyramid}!pacbell!key!sjc Steve Correll I am accustomed to extremely aggressive optimization, both that which has been implemented and that which I've only thought about. The program you show above, "EXTERNAL X;END", is indeed standard-conforming even if X is not available, because X is not necessarily a procedure: in fact it appears the standard requires that it must be a BLOCK DATA subprogram. (Because in the main program unit, it is not referenced as a subroutine or function, and a BLOCK DATA subprogram is the only alternative.) Unfortunately, the standard does not appear to specify the effect of specifying a BLOCK DATA subprogram name in an EXTERNAL statement. So it appears that your mythical user complaining about a processor refusing to construct an executable program in the absence of X indeed has a point: it is a valid program, and X need not be present, even though I would argue a reasonable implementation should complain that there is no BLOCK DATA X (via an error message from, perhaps, a multi-language linker requiring the user to look up the message in the Fortran book to yield the explanation that perhaps a BLOCK DATA X is missing). However, as I pointed out in my original posting, the only reasonably way for an implementation to deal with "EXTERNAL FOO" where FOO is not referenced anywhere else in the same program unit is for it to assume FOO is a BLOCK DATA program unit and to ensure that, if it indeed turns out that FOO is found to be a BLOCK DATA program unit, its initial values for variables in COMMON are used for the program. If FOO turns out to be a subroutine or function, an implementation is free to ignore it, if it is capable of doing that while still dealing with the possible BLOCK DATA FOO case instead. Now, you can play language lawyer games -- like the company that said their implementation was standard-conforming even though the STOP statement did not in fact stop the program, because the standard didn't actually specify what happens the moment after the program is "stopped" -- and say that an implementation is standard-conforming that totally ignores EXTERNAL FOO where FOO is otherwise unreferenced in the program unit. However, if you are taking things this literally from a standards perspective, then please note that there is NO STANDARD WAY to initialize variables in common! According to the standard, that can ONLY be done via BLOCK DATA. And a system that provides some mechanism whereby BLOCK DATA can be ignored (the "library problem" that started all this), and yet refuses to honor a clear accommodation in the standard to deal with the problem, fails to honor the spirit of the standard, just as does one that, when running a program saying "PRINT *,2.0*3.0", outputs "2.0" because the standard doesn't actually specify precision requirements. After all, if subroutines and functions need only be "available" when they are actually "referenced" at run time, then (unless there's some wording to override this assumption in the standard that I can't remember seeing offhand), the same goes for BLOCK DATA in a system that implements everything using libraries. Yet there is NO WAY to "reference" a BLOCK DATA subprogram except via the "EXTERNAL FOO" construct. (And note that your reference to complaints about unSAVEd variables not being SAVEd is, in my opinion, an invalid comparison in this context. The spirit of the standard regarding BLOCK DATA is as I state above; whereas the standard clearly states that you can't depend on the value of an unSAVEd variable between procedure invocations. People complaining about a system not honoring the EXTERNAL FOO convention for ensuring the linking-in of a BLOCK DATA FOO residing in a library have a very legitimate gripe, language-lawyer games notwithstanding. People who complain about unSAVEd variables not retaining their values between procedure invocations are just plain wrong; but note that many implementations nevertheless provide command- line qualifiers to effectively force the SAVEing of all appropriate variables, so given that so many implementations bend over backwards to accommodate incorrect or very old code, why not deal with the relatively trivial case of EXTERNAL FOO possibly referring to a necessary BLOCK DATA FOO?) James Craig Burley, Software Craftsperson burley@world.std.com