libiberty and getopt

David Fritz zeroxdf@att.net
Thu Apr 29 10:27:00 GMT 2004


bertrand marquis wrote:

> Hi again,
> 
>    i just find the solution to my problem
>    in fact it seems that adding:
> 
> extern int optind;
> extern char *optarg;
> 
> solve the problem. The compiler then auto-import these variables and it 
> is working after. This problem doesn't seem to exist under linux but it 
> could be a difference in versions between my linux and my cygwin.
> 
> bertrand marquis a écrit:
> 
>> Hi,
>>
>>    I need to compile a program using libiberty.a and the function 
>> getopt_long. When compiling with the flag -liberty my program crash 
>> because it don't take the right arguments from the command line. But 
>> without libiberty this part work before.
>>
>> i made a small program showing that problem, if anyone has an idea ?
>> i'm using the latest cygwin from the installer ,gcc-3.3.1 and ld 
>> 2.15.90 20040312
>>
>> thanks
>>
>> You can find next my source code for the test program and the result i 
>> have with it.
>>
>>
>> My test program:
>>
>> /*begin of argu.c*/
>> #include <unistd.h>
>> #include <getopt.h>
>> #include <ctype.h>
>> #include <stdio.h>
>>
>> int main(int argc, char **argv) {
>>
>>    struct option long_opts[] = {
>>    {"v", 1, 0, 'v'},
>>    {"no-v", 0, 0, 'V'},
>>    {"k", 1, 0, 'k'},
>>    {"no-k", 0, 0, 'K'},
>>    {"l", 1, 0, 'l'},
>>    {"no-l", 0, 0, 'L'},
>>    {0, 0, 0, 0}
>>    };
>>    int c;
>>    while ((c = getopt_long(argc, argv, "v:Vk:Kl:L:",
>>        long_opts, NULL)) != EOF) {
>>
>>    switch(c) {
>>    case 'v':
>>        printf("v %s\n",optarg);
>>        break;
>>    case 'V':
>>        printf("V\n");
>>        break;
>>    case 'k':
>>        printf("k %s\n",optarg);
>>        break;
>>    case 'K':
>>        printf("K\n");
>>        break;
>>    case 'l':
>>        printf("l %s\n",optarg);
>>        break;
>>    case 'L':
>>        printf("L\n");
>>        break;
>>    case '?':
>>        printf("other:%c\n",c);
>>    }
>>    }
>>    printf("argc=%d , optind=%d , 
>> file=%s\n",argc,optind,argc>optind?*(argv+optind):"none");
>>    return 0;
>> }
>> /*end of argu.c*/
>>
>> when you compile it with : gcc argu.c -o argu.exe it works:
>> $ ./argu.exe -v abc -K test
>> v abc
>> K
>> argc=5 , optind=4 , file=test
>>
>> but when you compile it with gcc argu.c -o argu.exe -liberty it gives:
>> $ ./argu.exe -v abc -K test
>> v (null)
>> K
>> argc=5 , optind=1 , file=-v

When you link with libiberty you are linking to an implementation of getopt* 
that does not correspond to the headers you have included.

There is no symbol called _optarg (or _optind, etc.) in libcygwin.a.  The Cygwin 
headers declare the opt* variables __declspec(dllimport).  So when you include 
the Cygwin headers, when you refer to optarg the symbol that gets generated is 
__imp__optarg, which /is/ exported from libcygwin.a.  The version of getopt* in 
libiberty refers to symbols named _opt* and not __imp__opt*.  So when you link 
against libiberty, your program and getopt() are referring to different opt* 
variables.

When you re-declare the opt* variables, you effectively undo the 
__declspec(dllimport) so your program again refers to _opt* instead of 
__imp__opt*.  MSVC issues a warning in this case; gcc, it seems, does not.

A better way to solve this, I think, would be to link against libcygwin.a before 
libiberty.a.

~$ gcc argu.c -o argu.exe -lcygwin -liberty
~$ ./argu.exe -v abc -K test
v abc
K
argc=5 , optind=4 , file=test


FWIW, this has come up before:

http://sources.redhat.com/ml/cygwin/2004-02/msg00063.html


HTH, Cheers


--
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/



More information about the Cygwin mailing list