Why does linker fail to resolve dependencies within the same .a file?

2007-02-27 Thread Christian Convey

I'm using CMake to build a library (as a .a file) and a demo program
for that library.


My problem is that when I go to link that demo program, I get a linker
error that says one file function in the .a file can't find another
function in the .a file.  Here's what the linker command line and
error output look like:


Linking CXX executable simpleIO
cd /home/cjc/csc583-svn/uriVisionLib/trunk/SDK/Demos/C++/Basic/Simple_IO
&& /home/cjc/packages/CMake/bin/cmake -P
CMakeFiles/simpleIO.dir/cmake_clean_target.cmake
cd /home/cjc/csc583-svn/uriVisionLib/trunk/SDK/Demos/C++/Basic/Simple_IO
&& /usr/bin/c++  -fPIC "CMakeFiles/simpleIO.dir/main_IO.o"   -o
simpleIO -rdynamic
-L/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++ -lGL
-lglut -Wl,-Bstatic -luriVision -luriVision -Wl,-Bdynamic
-Wl,-rpath,/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++
/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++/liburiVision.a(ImageReader.o):
In function `uriVideoSources::ImageReader::getFrame(bool,
uriBase::RasterImage*)':
ImageReader.cpp:(.text+0x90): undefined reference to
`uriVideoSources::ImageReader_gen::getFrame_(bool,
uriBase::RasterImage*)'


(there are more errors as well, but I figured this was enough to make my point).

I thought that perhaps the supposedly missing function wasn't in the
.a file, so I check with nm as follows:


[EMAIL PROTECTED]:~$ nm --demangle
/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++/liburiVision.a
| grep outputFrame
002c T uriMovieEditing::ImageWriter::outputFrame(uriBase::RasterImage*)
 T uriMovieEditing::ImageWriter::outputFrame(uriBase::RasterImage*,
bool)
   U uriMovieEditing::ImageWriter_gen::outputFrame_(uriBase::RasterImage*,
bool)



So it appears to be in there.  I also thought that maybe this was one
of the cases where I needed to list the .a file twice on the linker
command line, but the linker invocation / output shown above already
reflects my doing that (I think).


Does anyone know where I might be going wrong here?

Thanks,
Christian


Re: Linker problems: dependencies with .a file not resolved?

2007-02-28 Thread Christian Convey

On 27 Feb 2007 21:11:26 -0800, Ian Lance Taylor <[EMAIL PROTECTED]> wrote:

"Christian Convey" <[EMAIL PROTECTED]> writes:

> ImageReader.cpp:(.text+0x90): undefined reference to
> `uriVideoSources::ImageReader_gen::getFrame_(bool,
> uriBase::RasterImage*)'
>
> (there are more errors as well, but I figured this was enough to make my 
point).
>
> I thought that perhaps the supposedly missing function wasn't in the
> .a file, so I check with nm as follows:
>
> [EMAIL PROTECTED]:~$ nm --demangle
> /home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++/liburiVision.a
> | grep outputFrame
> 002c T uriMovieEditing::ImageWriter::outputFrame(uriBase::RasterImage*)
>  T uriMovieEditing::ImageWriter::outputFrame(uriBase::RasterImage*,
> bool)
>  U 
uriMovieEditing::ImageWriter_gen::outputFrame_(uriBase::RasterImage*,
> bool)

The error above refers to
uriVideoSources::ImageReader_gen::getFrame_(bool, uriBase::RasterImage*)
You didn't show whether the library defines that symbol or not.

Ian



Sorry, I re-typed the operation to have output for my email and
goofed.  But the symbol really does appear to be in the archive:

[EMAIL PROTECTED]:~$ nm --demangle
/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++/liburiVision.a
| grep "uriVideoSources::ImageReader_gen::getFrame"
U uriVideoSources::ImageReader_gen::getFrame_(bool)
U uriVideoSources::ImageReader_gen::getFrame_(bool,
uriBase::RasterImage*)


Why does linker fail to resolve dependencies within the same .a file?

2007-02-28 Thread Christian Convey

On 2/28/07, Nick Clifton <[EMAIL PROTECTED]> wrote:

Hi Christian,

> /usr/bin/c++ -fPIC "CMakeFiles/simpleIO.dir/main_IO.o" -o
> simpleIO -rdynamic
> -L/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++ -lGL
> -lglut -Wl,-Bstatic -luriVision -luriVision -Wl,-Bdynamic
> -Wl,-rpath,/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++

Note: Placing "-luriVision" twice on the command line next to each other
like that will not actually gain you anything.  The only reason to
include a library more than once on a linker command line is if it
contains symbols that are referenced by files that are placed after the
first occurrence of the library on the command line.  eg:

   foo.o -lbar baz.o -lbar

The second "-lbar" is only needed if baz.o includes references to
symbols that are defined in libbar.a which will not be pulled in when
resolving the references made by foo.o.


I'm not so sure that's true, because someone said that putting "bar.a"
on the linker command line is pretty much identical in effect to
listing, on the command line, the files that got bundled up into
bar.a.  So if bar.a is made up of x.o, y.o and z.o, and z.o contains a
function that depends on a function in x.o, then I really do need to
list bar.a twice in order to resolve that dependency. No?



> In function `uriVideoSources::ImageReader::getFrame(bool,
> uriBase::RasterImage*)':
> ImageReader.cpp:(.text+0x90): undefined reference to
> `uriVideoSources::ImageReader_gen::getFrame_(bool,
> uriBase::RasterImage*)'

> [EMAIL PROTECTED]:~$ nm --demangle
> /home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++/liburiVision.a
> | grep outputFrame

As has already been pointed out you are greping for 'outputFrame' when
the error message you have reported was for a missing 'getFrame_'
symbol.  I assume therefore that you are also getting error messages
about a missing reference to 'outputFrame_' ?


I pasted an irrelevant example by accident, but I really am seeing the
problem in question (I think).  Here's the link command and my first
error message from it:

cd /home/cjc/csc583-svn/uriVisionLib/trunk/SDK/Demos/C++/Basic/Simple_IO
&& /usr/bin/c++  -fPIC "CMakeFiles/simpleIO.dir/main_IO.o"   -o
simpleIO -rdynamic
-L/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++ -lGL
-lglut -Wl,-Bstatic -luriVision -luriVision -Wl,-Bdynamic
-Wl,-rpath,/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++
/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++/liburiVision.a(ImageReader.o):
In function `uriVideoSources::ImageReader::getFrame(bool,
uriBase::RasterImage*)':
ImageReader.cpp:(.text+0x90): undefined reference to
`uriVideoSources::ImageReader_gen::getFrame_(bool,
uriBase::RasterImage*)'

and here's the (hopefully) telling nm/grep statement:

[EMAIL PROTECTED]:~$ nm --demangle
/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++/liburiVision.a
| grep "uriVideoSources::ImageReader_gen::getFrame"
U uriVideoSources::ImageReader_gen::getFrame_(bool)
U uriVideoSources::ImageReader_gen::getFrame_(bool,
uriBase::RasterImage*)


Re: Why does linker fail to resolve dependencies within the same .a file?

2007-02-28 Thread Christian Convey

I stand corrected on so many points here that I think I'll have
bruises when I wake up tomorrow :)  Thanks for all the help.

To put a happy (though embarrassing) end to the story: I was missing a
few .cpp files when constructing the library.  Not a problem at
compile-time, because the headers were still accessible to those units
that needed them.  Adding those .cpp files to the .a solved all my
link problems.

Thanks a ton for everyone's help.

- Christian

On 2/28/07, Nick Clifton <[EMAIL PROTECTED]> wrote:

Hi Christian,

   [I have restored the CC to gcc@gcc.gnu.org as there may be other
people interested in this discussion].

>>foo.o -lbar baz.o -lbar
>>
>> The second "-lbar" is only needed if baz.o includes references to
>> symbols that are defined in libbar.a which will not be pulled in when
>> resolving the references made by foo.o.
>
> I'm not so sure that's true, because someone said that putting "bar.a"
> on the linker command line is pretty much identical in effect to
> listing, on the command line, the files that got bundled up into
> bar.a.  So if bar.a is made up of x.o, y.o and z.o, and z.o contains a
> function that depends on a function in x.o, then I really do need to
> list bar.a twice in order to resolve that dependency. No?

No.  :-)

A library is not, quite, the same thing as a bunch of object files.  For
one thing the linker *will* repeatedly search a library until no more
undefined symbols can be resolved.  So in your example x.o will be
pulled into the link because it is needed to resolve a reference in z.o
(which is presumably needed to resolve a reference from an object file
earlier on in the linker command line).

This is all described in the linker documentation as well.  Have a look
at the description of the linker command line option --start-group.


> I pasted an irrelevant example by accident, but I really am seeing the
> problem in question (I think).  Here's the link command and my first
> error message from it:
>
> /usr/bin/c++  -fPIC "CMakeFiles/simpleIO.dir/main_IO.o"   -o
> simpleIO -rdynamic
> -L/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++ -lGL
> -lglut -Wl,-Bstatic -luriVision -luriVision -Wl,-Bdynamic
> -Wl,-rpath,/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++

> 
/home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++/liburiVision.a(ImageReader.o):
> In function `uriVideoSources::ImageReader::getFrame(bool,
> uriBase::RasterImage*)':
> ImageReader.cpp:(.text+0x90): undefined reference to
> `uriVideoSources::ImageReader_gen::getFrame_(bool,
> uriBase::RasterImage*)'
>
> and here's the (hopefully) telling nm/grep statement:
>
> [EMAIL PROTECTED]:~$ nm --demangle
> /home/cjc/csc583-svn/uriVisionLib/trunk/Development/Source/C++/liburiVision.a
>
> | grep "uriVideoSources::ImageReader_gen::getFrame"
> U uriVideoSources::ImageReader_gen::getFrame_(bool)
> U uriVideoSources::ImageReader_gen::getFrame_(bool,
> uriBase::RasterImage*)

Well this tells me that ...getFrame_(bool.uriBase::RasterImage*) is an
*undefined* symbol referenced from inside liburiVision.a.  (Hence the
'U' attribute as displayed by nm).  Hence the linker is correct in
complaining that it cannot resolve the reference and hence you do need
to tell the linker where to find this symbol.

Where do you think the ...getFrame_(bool.uriBase::RasterImage*) symbol
is defined ?

Cheers
   Nick