Subject: g77, iargc, getarg don't work for shared linking on Cygwin
From: "Alan W. Irwin" <[email-masked]>
To: [email-masked]
Cc: Michael Lemke <[email-masked]>, Arjen Markus <[email-masked]>
Date: Tue, 29 Nov 2005 11:21:18 -0800 (PST)

The problem: iargc, and getarg work for g77 on Cygwin when programmes are
built with static linking but not when they are built with shared linking.
g77 platforms other than Cygwin do not have this problem.

Static linking builds an executable that works fine:

g77 -c chkargs.f -o chkargs.o
g77 --verbose -o tstarg.exe tstarg.f chkargs.o >g77_static.out 2>&1
./tstarg a b c
  Number arguments: 3
  0./tstarg
  1a
  2b
  3c

Shared linking builds an executable that does not work correctly.
iargc returns -1, and getarg returns blanks.

g77 -c chkargs.f -o chkargs.o
g77 -shared chkargs.o -o cygchkargs.dll \
     -Wl,--enable-auto-image-base \
     -Wl,--out-implib,libchkargs.dll.a
g77 --verbose -o tstarg.exe tstarg.f libchkargs.dll.a >g77_shared.out 2>&1
./tstarg a b c
  Number arguments: -1
  0
  1
  2
  3

Here is the fortran source code for the above tests:

tstarg.f:
       program tstarg
       call chkargs
       end
chkargs.f:
       subroutine chkargs
       integer i
       integer narg
       character*20 arg
       intrinsic iargc, getarg

       narg = iargc()
       write(*,*) 'Number arguments:', narg

C     Use narg = 3 to allow testing both iargc above and getarg below.
C     However, in tests must always call with 3 arguments!
       narg = 3
       do i = 0,narg
          call getarg(i,arg)
          write(*,*) i, arg
       enddo
       return
       end

Here is the g77 --verbose output in the static linking case:

g77_static.out:
Driving: g77 -v -o tstarg.exe tstarg.f chkargs.o -lfrtbegin -lg2c
Reading specs from /usr/lib/gcc/i686-pc-cygwin/3.4.4/specs
Configured with: /gcc/gcc-3.4.4/gcc-3.4.4-1/configure --verbose --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --enable-languages=c,ada,c++,d,f77,java,objc --enable-nls --without-included-gettext --enable-version-specific-runtime-libs --without-x --enable-libgcj --disable-java-awt --with-system-zlib --enable-interpreter --disable-libgcj-debug --enable-threads=posix --enable-java-gc=boehm --disable-win32-registry --enable-sjlj-exceptions --enable-hash-synchronization --enable-libstdcxx-debug : (reconfigured) 
Thread model: posix
gcc version 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125)
  /usr/lib/gcc/i686-pc-cygwin/3.4.4/f771.exe tstarg.f -quiet -dumpbase tstarg.f -mtune=pentiumpro -auxbase tstarg -version -o /cygdrive/c/DOCUME~1/HP_EIG~1/LOCALS~1/Temp/cc3DksMj.s
GNU F77 version 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125) (i686-pc-cygwin)
 	compiled by GNU C version 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125).
GGC heuristics: --param ggc-min-expand=64 --param ggc-min-heapsize=65446
  /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/bin/as.exe -o /cygdrive/c/DOCUME~1/HP_EIG~1/LOCALS~1/Temp/ccnj0mYl.o /cygdrive/c/DOCUME~1/HP_EIG~1/LOCALS~1/Temp/cc3DksMj.s
  /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic --dll-search-prefix=cyg -o tstarg.exe /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../crt0.o -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../.. /cygdrive/c/DOCUME~1/HP_EIG~1/LOCALS~1/Temp/ccnj0mYl.o chkargs.o -lfrtbegin -lg2c -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc

The last line is the key one so I repeat it in wrapped form for clarity.

  /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic \
  --dll-search-prefix=cyg -o tstarg.exe \
  /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../crt0.o \
  -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 \
  -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 \
  -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../.. \
  /cygdrive/c/DOCUME~1/HP_EIG~1/LOCALS~1/Temp/ccnj0mYl.o \
  chkargs.o -lfrtbegin \
  -lg2c -lgcc -lcygwin -luser32 -lkernel32 \
  -ladvapi32 -lshell32 -lgcc

Here is the g77 --verbose output in the shared linking case:
g77_shared.out:
Driving: g77 -v -o tstarg.exe tstarg.f libchkargs.dll.a -lfrtbegin -lg2c
Reading specs from /usr/lib/gcc/i686-pc-cygwin/3.4.4/specs
Configured with: /gcc/gcc-3.4.4/gcc-3.4.4-1/configure --verbose --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --enable-languages=c,ada,c++,d,f77,java,objc --enable-nls --without-included-gettext --enable-version-specific-runtime-libs --without-x --enable-libgcj --disable-java-awt --with-system-zlib --enable-interpreter --disable-libgcj-debug --enable-threads=posix --enable-java-gc=boehm --disable-win32-registry --enable-sjlj-exceptions --enable-hash-synchronization --enable-libstdcxx-debug : (reconfigured) 
Thread model: posix
gcc version 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125)
  /usr/lib/gcc/i686-pc-cygwin/3.4.4/f771.exe tstarg.f -quiet -dumpbase tstarg.f -mtune=pentiumpro -auxbase tstarg -version -o /cygdrive/c/DOCUME~1/HP_EIG~1/LOCALS~1/Temp/ccmrjVaM.s
GNU F77 version 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125) (i686-pc-cygwin)
 	compiled by GNU C version 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125).
GGC heuristics: --param ggc-min-expand=64 --param ggc-min-heapsize=65446
  /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/bin/as.exe -o /cygdrive/c/DOCUME~1/HP_EIG~1/LOCALS~1/Temp/ccMT8siq.o /cygdrive/c/DOCUME~1/HP_EIG~1/LOCALS~1/Temp/ccmrjVaM.s
  /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic --dll-search-prefix=cyg -o tstarg.exe /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../crt0.o -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../.. /cygdrive/c/DOCUME~1/HP_EIG~1/LOCALS~1/Temp/ccMT8siq.o libchkargs.dll.a -lfrtbegin -lg2c -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc

The last line is the key one so I repeat it in wrapped form for clarity.

  /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic \
  --dll-search-prefix=cyg -o tstarg.exe \
  /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../crt0.o \
  -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 \
  -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 \
  -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../.. \
  /cygdrive/c/DOCUME~1/HP_EIG~1/LOCALS~1/Temp/ccMT8siq.o \
  libchkargs.dll.a -lfrtbegin \
  -lg2c -lgcc -lcygwin -luser32 -lkernel32 \
  -ladvapi32 -lshell32 -lgcc

Version information:

The above results were obtained with a Cygwin version
installed as of 2005-11-14.  The setup for that environment showed
a version of 2.510.2.2.  The particular g77 package version used for the
above results was gcc-g77-3.4.4-1, but we also got similar (bad) results
for gcc-g77-3.3.3-3.

Background information:

I am one of the developers for PLplot, a scientific plotting package that
has been ported to many different Unix and Linux platforms.  In our
experience, the fortran interface to PLplot has failed command-line parsing
(iargc returning -1 and getarg returning blanks) only for the specific
combination of shared libraries and the Cygwin platform. I have no direct
experience with Cygwin, but I am reporting the above results from one of our
PLplot developers who does have access to that platform. Please let me know
if there is any other information you require to verify this Cygwin-specific
g77 bug.

"info g77" specifically mentions that there are unique linking requirements
to initialize iargc and getarg properly.  In particular, "main" (provided by
libg2c) has to be called and libg2c linked correctly.  Apparently some aspect
of that has not been done correctly for the shared linking case for
the g77 Cygwin package.

Michael Lemke has recognized this special g77/Cygwin problem before, see his
post to this list at http://www.cygwin.com/ml/cygwin/2001-04/msg01313.html.
I don't fully understand the linking issues presented there, but the
conclusion was

"The only way out of this I see is to make libg2c itself a dll."

I notice that the package gcc-g77-3.4.4-1 only includes a static version
of libg2c so if the above post is correct, that is the source of the problem.

For my own Debian stable system, libg2c appears both in static and shared
form so there should be no fundamental g77 issues in creating a dll version
of libgc2 for the g77 Cygwin package.  Furthermore, many other Cygwin
packages have dual static and dll libraries as well so I presume it will be
straightforward to do the same for the Cygwin/g77 libgc2 library.

Thanks in advance for any help with this issue.  We will be happy to try any
temporary workarounds you propose. Command-line parsing is important for
PLplot users (and presumably many other fortran users) because it helps
tremendously with ease of use.  Of course, one fall back is to restrict our
Cygwin platform use to static library builds of PLplot, but that restrics
PLplot in a number of other ways (e.g., are python and java interfaces
require shared linking).

Alan
__________________________
Alan W. Irwin
email: [email-masked]
phone: 250-727-2902

Astronomical research affiliation with Department of Physics and Astronomy,
University of Victoria (astrowww.phys.uvic.ca).

Programming affiliations with the FreeEOS equation-of-state implementation
for stellar interiors (freeeos.sf.net); PLplot scientific plotting software
package (plplot.org); the Yorick front-end to PLplot (yplot.sf.net); the
Loads of Linux Links project (loll.sf.net); and the Linux Brochure Project
(lbproject.sf.net).
__________________________

Linux-powered Science
__________________________

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/