Bug 53895

Summary: Linker doesn't handle the references in .a libraries located in different directories properly
Product: [Applications] kdevelop Reporter: Claudiu ANGHEL <claudiu.anghel>
Component: kdevelop 2.x (obsolete)Assignee: KDevelop-Devel List <kdevelop-devel>
Status: RESOLVED NOT A BUG    
Severity: normal    
Priority: NOR    
Version: 2.1.3   
Target Milestone: ---   
Platform: openSUSE   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: The source for the classes used for checking the bug

Description Claudiu ANGHEL 2003-02-02 13:13:41 UTC
Version:           2.1.3 (using KDE KDE 3.0.5)
Installed from:    SuSE RPMs
Compiler:          gcc (GCC) 3.2 GNU ld version 2.12.90.0.15 20020717 (SuSE)
OS:          Linux

If you create a class A in a directory dira and another class B in a directory dirb (class B will use the class A) the linker will give unsolved references  when will create the executable (see the output bellow). When I create the directories I choose static linked libraries.

Here is an example for reproducing the problem and also 2 workaround that I found.

Example: (only the relevant part is shown, the #if,#endif ... are skipped

Create a class with "New class ...". In the dialog box choose the name A1, change the files to be generated from a1.h to dira/a1.h and from a1.cpp to dira/a1.cpp.OK
Create a class with "New class ...". In the dialog box choose the name B1, change the files to be generated from b1.h to dirb/b1.h and from b1.cpp to dirb/b1.cpp.OK

Bellow is the generated code with the extra function added manually:

In directory dira:

File a1.h

class A1 {
public: 
	A1();
	~A1();
        void doA1(void);
};

File a1.cpp

A1::A1(){}
A1::~A1(){}
void A1::doA1(void) { printf("doA1\n");}

In directory dirb:

File b1.h

#include "../dira/a1.h"
class B1 {
public: 
	B1();
        void doB1(void);
	~B1();
};

File b1.cpp

B1::B1(){}
B1::~B1(){}
void B1::doB1(void) {
    A1 a;
    a.doA1();
}

In the root directory:

File main.cpp

#include "dirb/b1.h"

int main(int argc, char *argv[]) {
    B1 b;
    b.doB1();

  return EXIT_SUCCESS;
}

The genrated Makefile.am will look like this:

####### kdevelop will overwrite this part!!! (begin)##########
bin_PROGRAMS = bugtest

## INCLUDES were found outside kdevelop specific part

bugtest_SOURCES = main.cpp 
bugtest_LDADD   = ./dira/libdira.a ./dirb/libdirb.a 

SUBDIRS = docs dira dirb 

EXTRA_DIST = main.cpp 

####### kdevelop will overwrite this part!!! (end)############
# set the include path found by configure
INCLUDES= $(all_includes)
 
# the library search path.
bugtest_LDFLAGS = $(all_libraries) 

-- End of Makefile.am


At the linking time you'll receive:
gmake[3]: Entering directory `/home/claudiu/bugtest/bugtest' 
/bin/sh ../libtool --silent --mode=link --tag=CXX g++ -Wnon-virtual-dtor -Wno-long-long -Wbad-function-cast -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -O0 -g3 -Wall -fno-exceptions -fno-check-new -o bugtest main.o ./dira/libdira.a ./dirb/libdirb.a 
./dirb/libdirb.a(b1.o): In function `B1::doB1()': 
/home/claudiu/bugtest/bugtest/dirb/b1.cpp:25: undefined reference to `A1::A1[in-charge]()' 
/home/claudiu/bugtest/bugtest/dirb/b1.cpp:26: undefined reference to `A1::doA1()' 
/home/claudiu/bugtest/bugtest/dirb/b1.cpp:26: undefined reference to `A1::~A1 [in-charge]()' 
collect2: ld returned 1 exit status

Workarounds:
Workaround 1:

Add in your main function a reference to A1 class (eg. create an object of type A1)

int main(int argc, char *argv[]) {
    A1 a;
    B1 b;

    b.doB1();
    return EXIT_SUCCESS;
}
This one will work without running the automake or autoconf again.

Workaround 2:
Edit your Makefile.am in the root directory and change the line
bugtest_LDADD   = ./dira/libdira.a ./dirb/libdirb.a 
with
bugtest_LDADD   = ./dira/*.o ./dirb/libdirb.a 
This latest solution is not so good because the KDE will rewrite sometimes the Makefile.am

I don't know if this a ld bug or an automake, kde bug (is not setting the proper flags for linking).
Comment 1 Claudiu ANGHEL 2003-02-02 15:48:51 UTC
Created attachment 864 [details]
The source for the classes used for checking the bug

Contains the source files used for checking the bug
Comment 2 Caleb Tennis 2003-02-09 17:27:26 UTC
This would work better if you switch the order: 
 
bugtest_LDADD = ./dirb/libdirb.a ./dira/libdira.a 
 
GCC compiling is very specific about the order of static libraries when they 
have dependencies on each other.  I don't remember if you can switch the order 
easily in KDevelop 2.x, but you can in 3.0. 
 
 
Comment 3 Claudiu ANGHEL 2003-02-09 17:41:03 UTC
Subject: Re:  Linker doesn't handle the references in .a libraries
 located in different directories properly

Thank you for your response,

Unfortunately the LDADD line is generated by KDevelop and any 
modification will be overwriten every time you change the directory 
structure.
Is very strange that if you don't link the .a archives but .o objects 
you have no linking problem.
For the moment I'm making a dummy call in a dummy function in the main 
directory for forcing the linking of the contents of library.
Maybe I should download kdevelop 3.0, but I'm not so confident in alpha 
versions.

Thank you once more,
Claudiu ANGHEL

Caleb Tennis wrote:

>------- You are receiving this mail because: -------
>You reported the bug, or are watching the reporter.
>     
>http://bugs.kde.org/show_bug.cgi?id=53895     
>caleb@aei-tech.com changed:
>
>           What    |Removed                     |Added
>----------------------------------------------------------------------------
>             Status|UNCONFIRMED                 |RESOLVED
>         Resolution|                            |INVALID
>
>
>
>------- Additional Comments From caleb@aei-tech.com  2003-02-09 17:27 -------
>This would work better if you switch the order: 
> 
>bugtest_LDADD = ./dirb/libdirb.a ./dira/libdira.a 
> 
>GCC compiling is very specific about the order of static libraries when they 
>have dependencies on each other.  I don't remember if you can switch the order 
>easily in KDevelop 2.x, but you can in 3.0.
>
>
>  
>