public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: linking problem - "undefined reference   to  ..."
@ 2008-04-10  3:24 Chris Bouchard
  0 siblings, 0 replies; 5+ messages in thread
From: Chris Bouchard @ 2008-04-10  3:24 UTC (permalink / raw)
  To: gcc-help

Brian,

>#ifdef __cplusplus
>extern "C" {
>#endif
>
>and near the end:
>
>#ifdef __cplusplus
>}
>#endif
>
>The preprocessor symbol __cplusplus is defined when the file is being
>compiled as C++, and is used to wrap all the declarations with a large
>"extern "C" { ... }".  The reason for the #ifdef is that so it remains a
>valid C file as well.

I wrapped the header file's declarations with "extern "C" { ... }" and it worked!  Thank you very much.

>That or:
>
>mv fig6.cpp fig6.c
>gcc -o fig6 fig6.c -L. -ltsil

I tried this first but got the same error message...

Thanks again for all your help.  I'm now using the software application!

Chris Bouchard

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: linking problem - "undefined reference  to  ..."
  2008-04-10  1:14 Chris Bouchard
@ 2008-04-10  1:53 ` Brian Dessent
  0 siblings, 0 replies; 5+ messages in thread
From: Brian Dessent @ 2008-04-10  1:53 UTC (permalink / raw)
  To: Chris Bouchard; +Cc: gcc-help

Chris Bouchard wrote:

> I searched the library and found:
> --------------------------------------------------------
> [cbouchrd@lx6 ~/tsil-1.1]$ nm -AP libtsil.a | grep ' T '
> [snip other functions]
> libtsil.a[initialize.o]: TSIL_SetParameters T 0000030a 00000c6d
> [snip other functions]
> --------------------------------------------------------
> I see the addition of T 0000030a00000c6d at the end of the function name... is this the name mangling you're talking about?

No, those are just the address within the object and the size.  The
mangled name would look something like
"_Z18TSIL_SetParametersP9TSIL_Dataeeeeee".  In fact you can see what it
is exactly by looking at how g++ encodes the call:

g++ -S fig6.cpp -o - | grep TSIL_SetParameters

> I did get the library from elsewhere.  Is their a way to enforce compatibility?  
In a sense, yes.  C has a much more stable and unchanging ABI, and is
callable from C++.  So it is much easier to distribute a C library and
have it usable by everyone than it is to distribute a C++ library.

> Perhaps by forcing compilation by a specific ABI version of gcc using an option I seem to remember reading about... okay I just looked it up... would "-fabi-version=n" fix this?

I don't know what the extent of what -fabi-version is able to change,
but it's not significant.  There's no switch to make a 4.3 gcc ABI
compatible with 3.3 gcc for example, nor one to make gcc compatible with
the C++ ABI of other vendors' compilers.  But that's not relevant here
as this is a C library.

> >From the website where I downloaded the code, "It is written in C, and can be linked to C/C++ and Fortran applications."  So, perhaps I should alter the tsil.h header to declare all extern "C".
> 
> I must admit, I don't know what this means or how to do it but I'll get my books out and start studying.  I also don't know what the statement "if __cplusplus is true" means.

If you look at some headers for common C libraries you will often see
near the top:

#ifdef __cplusplus
extern "C" {
#endif

and near the end:

#ifdef __cplusplus
}
#endif

The preprocessor symbol __cplusplus is defined when the file is being
compiled as C++, and is used to wrap all the declarations with a large
"extern "C" { ... }".  The reason for the #ifdef is that so it remains a
valid C file as well.

> 2.  maybe the library is a C library and I should declare the functions in tsil.h as extern "C"

That or:

mv fig6.cpp fig6.c
gcc -o fig6 fig6.c -L. -ltsil

Brian

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: linking problem - "undefined reference  to  ..."
@ 2008-04-10  1:14 Chris Bouchard
  2008-04-10  1:53 ` Brian Dessent
  0 siblings, 1 reply; 5+ messages in thread
From: Chris Bouchard @ 2008-04-10  1:14 UTC (permalink / raw)
  To: gcc-help

Brian,

Thanks for the quick response.

---- Original message ----
>Date: Wed, 09 Apr 2008 16:44:47 -0700
>From: Brian Dessent <brian@dessent.net>  
>Subject: Re: linking problem - "undefined reference to  ..."  
>To: Chris Bouchard <cbouchrd@uiuc.edu>
>Cc: gcc-help@gcc.gnu.org
>
>Chris Bouchard wrote:
>
>> #include "/home/theorist/cbouchrd/local/include/tsil.h"
>
>The absolute path is a bad idea, you can simply use #include "tsil.h".
>
>> ---------------------------------------------------------
>> [cbouchrd@lx6 ~/tsil-1.1]$ g++ -t -o fig6.exe fig6.cpp -L. -ltsil
>> ---------------------------------------------------------
>> where I think I'm telling gcc to go to the working directory to look for library files (-L.) and then to link to libtsil.a (-ltsil).
>
>That looks fine, although creating a binary named 'fig6.exe' on a
>platform like Linux that does not typically have an extension for
>executables seems really strange.  But that's neither here nor there,
>and shouldn't be related to the link errors.
>
>> /tmp/ccp26z8w.o(.text+0x96): In function `main':
>> : undefined reference to `TSIL_SetParameters(TSIL_Data*, long double, long double, long double, long double, long double, long double)'
>
>If gcc was unable to find "-ltsil" you would have gotten a different
>error saying as much, so that means that it did find and search
>libtsil.a for the symbol but did not find it.  You need to figure out if
>indeed the library has that symbol in it.  For static archives, 'nm' is
>usually used.  I like to use the idiom
>
>nm -AP libtsil.a | grep ' T ' 
>
>This prints the symbols	in the library, filtered on those marked 'T'
>which are the functions actually contained in the library.  You can add
>on an additional "| grep TSIL_SetParameters" to the end if you want to
>search for that specific function.
>

I searched the library and found:
--------------------------------------------------------
[cbouchrd@lx6 ~/tsil-1.1]$ nm -AP libtsil.a | grep ' T '
[snip other functions]
libtsil.a[initialize.o]: TSIL_SetParameters T 0000030a 00000c6d
[snip other functions]
--------------------------------------------------------
I see the addition of T 0000030a00000c6d at the end of the function name... is this the name mangling you're talking about?

>Since this is C++ you also have to be aware of name mangling.  The
>symbol will not be called as just 'TSIL_SetParameters' but some uglified
>version that encodes its type.  And in fact this is why I suspect the
>link is failing: in C++ due to this name mangling, libraries must all be
>ABI compatible which in most cases means they must have been compiled by
>the same compiler or two compatible versions of the same compiler.  In
>the case of gcc this usually means they must be from the same branch,
>e.g. gcc A.B.x and A.B.y.  You didn't mention if you compiled libtsil.a
>yourself or got it from elsewhere, but if the latter I suspect it's not
>ABI compatible.
>

I did get the library from elsewhere.  Is their a way to enforce compatibility?  Perhaps by forcing compilation by a specific ABI version of gcc using an option I seem to remember reading about... okay I just looked it up... would "-fabi-version=n" fix this?
 
I think the following means I'm using ABI version 2.
------------------------------------------------------
[cbouchrd@lx6 ~/tsil-1.1]$ g++ -E -dM - < /dev/null | awk '/GXX_ABI/ {print $3}'
1002
------------------------------------------------------

>Another related form of this problem is trying to link a C library from
>C++ code.  Again, the mangling makes this impossible unless you
>explicitly declare the functions as 'extern "C"' which disables the C++
>calling conventions.  If the output of 'nm' doesn't show mangled
>function names then the library is actually a C library and you need to
>rethink how you intend to use it.  You'd need to either switch to C for
>your code, or fix the tsil.h header to declare everything extern "C" if
>__cplusplus is true.

From the website where I downloaded the code, "It is written in C, and can be linked to C/C++ and Fortran applications."  So, perhaps I should alter the tsil.h header to declare all extern "C".

I must admit, I don't know what this means or how to do it but I'll get my books out and start studying.  I also don't know what the statement "if __cplusplus is true" means. 

It sounds like I have two possible options:
1.  maybe using the -fabi flag to use abi version 1 could fix the problem (if the library was compiled under version 1)
2.  maybe the library is a C library and I should declare the functions in tsil.h as extern "C"

If you could point me in the right direction here I'd be grateful!

>
>Brian

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: linking problem - "undefined reference to  ..."
  2008-04-09 22:07 Chris Bouchard
@ 2008-04-10  0:52 ` Brian Dessent
  0 siblings, 0 replies; 5+ messages in thread
From: Brian Dessent @ 2008-04-10  0:52 UTC (permalink / raw)
  To: Chris Bouchard; +Cc: gcc-help

Chris Bouchard wrote:

> #include "/home/theorist/cbouchrd/local/include/tsil.h"

The absolute path is a bad idea, you can simply use #include "tsil.h".

> ---------------------------------------------------------
> [cbouchrd@lx6 ~/tsil-1.1]$ g++ -t -o fig6.exe fig6.cpp -L. -ltsil
> ---------------------------------------------------------
> where I think I'm telling gcc to go to the working directory to look for library files (-L.) and then to link to libtsil.a (-ltsil).

That looks fine, although creating a binary named 'fig6.exe' on a
platform like Linux that does not typically have an extension for
executables seems really strange.  But that's neither here nor there,
and shouldn't be related to the link errors.

> /tmp/ccp26z8w.o(.text+0x96): In function `main':
> : undefined reference to `TSIL_SetParameters(TSIL_Data*, long double, long double, long double, long double, long double, long double)'

If gcc was unable to find "-ltsil" you would have gotten a different
error saying as much, so that means that it did find and search
libtsil.a for the symbol but did not find it.  You need to figure out if
indeed the library has that symbol in it.  For static archives, 'nm' is
usually used.  I like to use the idiom

nm -AP libtsil.a | grep ' T ' 

This prints the symbols	in the library, filtered on those marked 'T'
which are the functions actually contained in the library.  You can add
on an additional "| grep TSIL_SetParameters" to the end if you want to
search for that specific function.

Since this is C++ you also have to be aware of name mangling.  The
symbol will not be called as just 'TSIL_SetParameters' but some uglified
version that encodes its type.  And in fact this is why I suspect the
link is failing: in C++ due to this name mangling, libraries must all be
ABI compatible which in most cases means they must have been compiled by
the same compiler or two compatible versions of the same compiler.  In
the case of gcc this usually means they must be from the same branch,
e.g. gcc A.B.x and A.B.y.  You didn't mention if you compiled libtsil.a
yourself or got it from elsewhere, but if the latter I suspect it's not
ABI compatible.

Another related form of this problem is trying to link a C library from
C++ code.  Again, the mangling makes this impossible unless you
explicitly declare the functions as 'extern "C"' which disables the C++
calling conventions.  If the output of 'nm' doesn't show mangled
function names then the library is actually a C library and you need to
rethink how you intend to use it.  You'd need to either switch to C for
your code, or fix the tsil.h header to declare everything extern "C" if
__cplusplus is true.

Brian

^ permalink raw reply	[flat|nested] 5+ messages in thread

* linking problem - "undefined reference to  ..."
@ 2008-04-09 22:07 Chris Bouchard
  2008-04-10  0:52 ` Brian Dessent
  0 siblings, 1 reply; 5+ messages in thread
From: Chris Bouchard @ 2008-04-09 22:07 UTC (permalink / raw)
  To: gcc-help

All,

I'm getting the "undefined reference to ..." error, where ellipses represent any function I attempt to use that is, I believe at least partially, defined within an archived library file.  

Based on my Google research and gcc reference book, I think I'm improperly linking to the library file.  However, I'm unable to locate my mistake.  Any assistance would be greatly appreciated.  

Here's the nitty gritty, with "screen captures" between the dashed lines:

My version of gcc is:
---------------------------------------------------------
[cbouchrd@lx6 ~/tsil-1.1]$ gcc --version
gcc (GCC) 3.4.6 20060404 (Red Hat 3.4.6-8)
[snip]
---------------------------------------------------------

The library file (libtsil.a) resides in the same directory as the c++ file (fig6.cpp):
---------------------------------------------------------
[cbouchrd@lx6 ~/tsil-1.1]$ ls libtsil.a fig6.cpp
fig6.cpp  libtsil.a
---------------------------------------------------------

The c++ file looks like this (simplest form to illustrate  problem):
---------------------------------------------------------
#include "/home/theorist/cbouchrd/local/include/tsil.h"
int main () {
  TSIL_DATA foo;
  TSIL_REAL x,y,z,u,v,s,qq;
  TSIL_SetParameters (&foo,x,y,z,u,v,qq);
  return 0;
}
---------------------------------------------------------
where the data types TSIL_DATA and TSIL_REAL are defined in the header file (tsil.h).

My invocation of gcc goes like this:
---------------------------------------------------------
[cbouchrd@lx6 ~/tsil-1.1]$ g++ -t -o fig6.exe fig6.cpp -L. -ltsil
---------------------------------------------------------
where I think I'm telling gcc to go to the working directory to look for library files (-L.) and then to link to libtsil.a (-ltsil). 

The subsequent error message and associated info due to the -t flag is:
---------------------------------------------------------
/tmp/ccp26z8w.o(.text+0x96): In function `main':
: undefined reference to `TSIL_SetParameters(TSIL_Data*, long double, long double, long double, long double, long double, long double)'
/usr/bin/ld: link errors found, deleting executable `fig6.exe'
/usr/bin/ld: mode elf_i386
/usr/lib/gcc/i386-redhat-linux/3.4.6/../../../crt1.o
/usr/lib/gcc/i386-redhat-linux/3.4.6/../../../crti.o
/usr/lib/gcc/i386-redhat-linux/3.4.6/crtbegin.o
/tmp/ccp26z8w.o
-lstdc++_shared (/usr/lib/gcc/i386-redhat-linux/3.4.6/libstdc++_shared.so)
-lm (/usr/lib/gcc/i386-redhat-linux/3.4.6/../../../libm.so)
-lgcc_s (/usr/lib/gcc/i386-redhat-linux/3.4.6/libgcc_s.so)
/lib/libc.so.6
(/usr/lib/libc_nonshared.a)elf-init.oS
-lgcc_s (/usr/lib/gcc/i386-redhat-linux/3.4.6/libgcc_s.so)
/usr/lib/gcc/i386-redhat-linux/3.4.6/crtend.o
/usr/lib/gcc/i386-redhat-linux/3.4.6/../../../crtn.o
collect2: ld returned 1 exit status
---------------------------------------------------------

If there are any pieces of information that I should've provided but didn't please let me know... I'm a bit of a newbie.

Thanks,
Chris Bouchard

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-04-10  3:18 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-10  3:24 linking problem - "undefined reference to ..." Chris Bouchard
  -- strict thread matches above, loose matches on Subject: below --
2008-04-10  1:14 Chris Bouchard
2008-04-10  1:53 ` Brian Dessent
2008-04-09 22:07 Chris Bouchard
2008-04-10  0:52 ` Brian Dessent

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).