?
Solved

Nested libraries -- linker error

Posted on 2006-05-25
10
Medium Priority
?
747 Views
Last Modified: 2008-01-16
All,

I'm new to developing in gcc, ultimately for cross platform targets, and have hit a bump on trying to modularize my first bits of code.... I'm fairly motivated to get this going as I'm trying to set development standards for such endevors.  

Here's my draft attempt at defining the problem consisely.... TIA!

Scenerio (obsfucated):

I'm trying to break apart the code into what would seem to me to be logical, reusable libraries. Generally:
-- Library "first" is the most commonly called functions, intended as common to all my future projects
-- Library "second" makes use of the functions of library "first" and adds functions common to a few of my projects
-- Executable "third" also makes use of the functions of library "first", and functions of library "second"

Project "First" (static library)
libfirst.a contains some common logging functions, as generated by:
   first.c (function definitions)
   first.h (standard #includes/#definitions/function prototype declarations)
   ==> and where the function prototype declarations have been given "extern" storage class

Project "Second" (static library)
libsecond.a contains some common functions for a handful of projects, as generated by:
   second.c (function definitions, includes calls to logging functions in first.a)
   second.h (standard #includes/ ==> #include first.h <==/#definitions/function prototype declarations)

Project "Third" (executable)
third.exe will not link for reasons described below, and has files:
   third.c (function definitions -- including main(), includes calls to logging functions from first.a)
   third.h (standard #includes/==> #include second.h <==)


1) The first.a library compiles and archives successfully.  Issuing a:
#nm libfirst.a
produces the expected results... listing "first.o" as it's only member, followed by the standard and user-defined functions defined or used by first.c

2) The second.a library compiles and archives successfully. Issuing a:
#nm libsecond.a
produces a listing that lists second.o as it only member.  The standard and user-defined functions from first.c and second.c follow.

3) Compiling third.c/third.h compiles successfully.  In the link phase, the output contains entries such as:

#C:\cygwin\usr\local\lib/libfedmq.a(fedmq.o): In function `TraceDump':
#/usr/local/include/ifscommon.h:267: multiple definition of `_TraceDump'
#./fedmqmonitor.o:/usr/local/include/ifscommon.h:267: first defined here

Notes:

The development environment (IDE) is the CDT plugin for Eclipse, running under Cygwin.

The libfirst.a was:
   - generated using the CDT "Managed Make C Project"
   - has a project type "Static Library (Gnu on Windows)"

The libsecond.a was:
   - generated using the CDT "Managed Make C Project"
   - has a project type "Static Library (Gnu on Windows)"

The third.exe was:
   - generated using the CDT "Managed Make C Project"
   - has a project type "Executable (Gnu on Windows)"

Third.exe produces the same link errors if both first.h and second.h are included, there is no difference.


Questions:

1) Is the libsecond.a file supposed to have the functions of libfirst.a? That is, libfirst.a has 'extern'ed functions, should the archiver ("ar -r") have included them in libsecond.a?

2) Why is the duplicate function error not at issue when generating the libsecond.a project? That is, does the archiver check for duplicates as the linker does?

3) Ultimately:
===> What is the "right" way to structure and manage such a scenerio of nested libraries?
===> What is best practice?
===> What traps/pitfalls are there to using "nested" libraries (one library calling another)?




0
Comment
Question by:daveburrow
  • 3
  • 3
  • 2
  • +1
10 Comments
 
LVL 12

Expert Comment

by:rajeev_devin
ID: 16761603
>> #/usr/local/include/ifscommon.h:267: multiple definition of `_TraceDump'
This is not a linker error.
It is compilation error.
0
 
LVL 12

Expert Comment

by:rajeev_devin
ID: 16761608
>> This is not a linker error.
sorry. I din't read the question.
it is a linker error.
0
 
LVL 12

Expert Comment

by:rajeev_devin
ID: 16761636
first is a static library.
second is a static library.

and you are linking them to third
seems ok to me.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 45

Expert Comment

by:sunnycoder
ID: 16761894
Did you protect against mulitple inclusion? Each of your .h files should be structured like as shown below

#ifndef FIRST_H
#ifdef FIRST_H
//header file contents here
#endif /*FIRST_H -> this name would be unique for each header file in the project*/
0
 

Author Comment

by:daveburrow
ID: 16761939
yessir --- all .h files are so protected.... (as generated by the CDT IDE on file creation) and appear to be correct.
0
 
LVL 45

Expert Comment

by:sunnycoder
ID: 16762030
1. What was the exact command line for compiling the third library
Since all libraries are statically linked, it might so happen that second.o included a definition of function defined in first.o ... If third.o was linked to first.o and second.o, there would be multiple definitions of functions in first.o ... try compiling all .c files on a single command line instead on linking the .a files. Does that work?

2. Make sure that you are defining the TraceDump function only once - name should not be repeated in any of the files.
0
 

Author Comment

by:daveburrow
ID: 16762920
sunnycoder:

Thanks for the quick responses.... here's more verbose output.... :-)

To your previous "1." -- see the console outputs below. All .c files compile fine, just the link of the last output fails
To your previous "2." -- All functions are uniquely named across all three projects.

At the risk of logging ==>too<== much, I'm including the console output of the three project builds..... I can't expect help on limited information.

Where:
Project "first" is actually named "ifscommon"
Project "second" is actually named "fedmq"
Project "third" is actually named "MQMonitor"

To help understand the console outputs, please be aware that the "make" starts in the Debug folder of each project:

$(workspace_root)
     |
     |-> ifscommon
     |          |
     |          |-> Debug
     |          |         |-> makefile
     |          |-> ifscommon.c
     |          |-> ifscommon.h
     |
     |-> fedmq
     |          |
     |          |-> Debug
     |          |         |-> makefile
     |          |-> fedmq.c
     |          |-> fedmq.h
     |
     |-> MQMonitor
                |
                |-> Debug
                |         |-> makefile
                |-> MQMonitor.c
                |-> MQMonitor.h




Project "ifscommon" output......
==========================================================================
**** Full rebuild of configuration Debug for project ifscommon ****

make -k clean all
rm -rf  ./ifscommon.o  ./ifscommon.d libifscommon.a
 
Building file: ../ifscommon.c
Invoking: GCC C Compiler
gcc -I.. -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -oifscommon.o ../ifscommon.c
Finished building: ../ifscommon.c
 
Building target: libifscommon.a
Invoking: GCC Archiver
ar -r libifscommon.a ./ifscommon.o
ar: creating libifscommon.a
Finished building target: libifscommon.a
 
Build complete for project ifscommon
==========================================================================




Project "fedmq" output......
==========================================================================
**** Full rebuild of configuration Debug for project fedmq ****

make -k clean all
rm -rf  ./fedmq.o  ./fedmq.d libfedmq.a
 
Building file: ../fedmq.c
Invoking: GCC C Compiler
gcc -I.. -IC:\cygwin\usr\local\include -IC:\cygwin\usr\include -IC:\Program Files\IBM\WebSphere MQ\Tools\c\include -O0 -g3 -c -fmessage-length=0 -std=c99 -ofedmq.o ../fedmq.c
Finished building: ../fedmq.c
 
Building target: libfedmq.a
Invoking: GCC Archiver
ar -r libfedmq.a ./fedmq.o
ar: creating libfedmq.a
Finished building target: libfedmq.a
 
Build complete for project fedmq
==========================================================================



Project "MQMonitor" output......
==========================================================================
**** Full rebuild of configuration Debug for project MQMonitor ****

make -k clean all
rm -rf  ./fedmqmonitor.o  ./fedmqmonitor.d MQMonitor.exe
 
Building file: ../fedmqmonitor.c
Invoking: GCC C Compiler
gcc -I.. -IC:\Program Files\IBM\WebSphere MQ\Tools\c\include -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -ofedmqmonitor.o ../fedmqmonitor.c
Finished building: ../fedmqmonitor.c
 
Building target: MQMonitor.exe
Invoking: GCC C Linker
gcc -LC:\cygwin\usr\local\lib -LC:\Program Files\IBM\WebSphere MQ\Tools\Lib -oMQMonitor.exe ./fedmqmonitor.o -lpopt -lfedmq -lsqlite3 -lmqm
C:\cygwin\usr\local\lib/libfedmq.a(fedmq.o): In function `setTraceThreshold':
/usr/local/include/ifscommon.h:32: multiple definition of `_setTraceThreshold'
./fedmqmonitor.o:/usr/local/include/ifscommon.h:32: first defined here
C:\cygwin\usr\local\lib/libfedmq.a(fedmq.o): In function `TraceDump':
/usr/local/include/ifscommon.h:267: multiple definition of `_TraceDump'
./fedmqmonitor.o:/usr/local/include/ifscommon.h:267: first defined here
C:\cygwin\usr\local\lib/libfedmq.a(fedmq.o): In function `fDumpWrite':
/usr/local/include/ifscommon.h:311: multiple definition of `_fDumpWrite'
./fedmqmonitor.o:/usr/local/include/ifscommon.h:311: first defined here
C:\cygwin\usr\local\lib/libfedmq.a(fedmq.o): In function `fDumpRead':
/usr/local/include/ifscommon.h:358: multiple definition of `_fDumpRead'
./fedmqmonitor.o:/usr/local/include/ifscommon.h:358: first defined here
C:\cygwin\usr\local\lib/libfedmq.a(fedmq.o): In function `TraceLine':
/usr/local/include/ifscommon.h:223: multiple definition of `_TraceLine'
./fedmqmonitor.o:/usr/local/include/ifscommon.h:223: first defined here
collect2: ld returned 1 exit status
make: *** [MQMonitor.exe] Error 1
make: Target `all' not remade because of errors.
Build complete for project MQMonitor
==========================================================================




0
 
LVL 14

Accepted Solution

by:
cwwkie earned 2000 total points
ID: 16764919
> #/usr/local/include/ifscommon.h:267: multiple definition of `_TraceDump'

Can you post the lines around line #267 of /usr/local/include/ifscommon.h?
Looks like a definition instead of a declaration of TraceDump.
0
 

Author Comment

by:daveburrow
ID: 16765062

OK, so there's a big problem --- and one I missed entirely --- ifscommon.h has only 33 lines in the Project Folder.

So poking around I found that I had not exported the Project File version of ifscommon.h to "/usr/local/include",  so the include directory for the build of fedmq.c/.h was an old version that had far too many lines in it, of course including definitions.

Very good catch.... Thank-you!

So more info:  Having not be brought up in the c/c++ culture, after I had complied each project, I exported the .h file of each project to "/usr/local/include", so that I could use the angle bracket syntax (#include <header.h>) instead of the quoted syntax (#include "header.h").  

I just missed the export of one of the files.

All projects compile and link successfully now.  Thanks again!


0
 
LVL 14

Expert Comment

by:cwwkie
ID: 16765117
> so that I could use the angle bracket syntax (#include <header.h>) instead of the quoted syntax (#include "header.h").  

There is nothing wrong with the quoted syntax. If might even be easier to recognise your own header files.
But if you want to copy files around, you can consider including that in the makefile.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
Suggested Courses

755 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question