[g++] Probleem met static linken van mysqlclient

Pagina: 1
Acties:

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Hallo,

Ik probeer een server met een MySQL client te compilen op RH9. Omdat de server waar deze server op gaat draaien RH7 is, link ik alles static om problemen te voorkomen.

Totdat ik de MySQL client had toegevoegd ging dat goed. Als ik niet static link gaat het ook goed.

Ik gebruik de volgende command line en krijg de volgende error:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
g++ -I ../misc -L/usr/lib/mysql -lmysqlclient -o xwis -static ../misc/*.cpp ../misc/sql/*.cpp *.cpp

In file included from /usr/include/c++/3.2.2/backward/strstream:51,
                 from wol_client.cpp:8:
/usr/include/c++/3.2.2/backward/backward_warning.h:32:2: warning:
#warning This file includes at least one deprecated or antiquated header.
Please consider using one of the 32 headers found in section 17.4.1.2 of the C++
standard. Examples include substituting the <X> header for the <X.h> header for
C++ includes, or <sstream> instead of the deprecated header <strstream.h>. To
disable this warning use -Wno-deprecated.
/tmp/ccnBnwEN.o(.text+0x1b): In function `Cdatabase::open(char const*, char
const*, char const*, char const*)':
: undefined reference to `mysql_init'

Het gaat om de error, alhoewel ik die warning ook niet op kan lossen.
Waarom lukt het static linken niet?

.modbreak: even met wat enters gestrooid

[ Voor 9% gewijzigd door .oisyn op 18-06-2003 15:37 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

blijkbaar vind ie het symbool mysql_init niet. Weet je zeker dat je linkt met alle benodigde libs?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
.oisyn schreef op 18 juni 2003 @ 15:38:
blijkbaar vind ie het symbool mysql_init niet. Weet je zeker dat je linkt met alle benodigde libs?
Als ik -static weg laat, werkt het wel. En ik link altijd met alleen deze lib, dus volgens mij heb ik wel de goede lib te pakken.

De MySQL docs geven ook aan dat het deze lib moet zijn.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 18:13
Begin eens met het los compileren van alle bestanden, zodat je netjes per source file een object file krijgt. Vervolgens kan g++ je vertellen in welke sourcefile de foute referentie voorkomt. Vergelijk vervolgens eens de uitvoer van nm op libmysqlclient.a en die object file; als het goed is heb je een ongedefinieerd referentie in je object file zitten en een bijbehorende definitie in libmysqlclient.a.

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Soultaker schreef op 18 June 2003 @ 16:06:
Begin eens met het los compileren van alle bestanden, zodat je netjes per source file een object file krijgt. Vervolgens kan g++ je vertellen in welke sourcefile de foute referentie voorkomt. Vergelijk vervolgens eens de uitvoer van nm op libmysqlclient.a en die object file; als het goed is heb je een ongedefinieerd referentie in je object file zitten en een bijbehorende definitie in libmysqlclient.a.
De undefined reference zit in database.cpp. Overigens is dit slechts een van de undefined references, alle mysql_ functies geven de error.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost mysql]# nm libmysqlclient.a|grep mysql_init
nm: my_pthread.o: no symbols
nm: my_thr_init.o: no symbols
nm: thr_mutex.o: no symbols
nm: my_port.o: no symbols
nm: getopt.o: no symbols
nm: getopt1.o: no symbols
nm: strmov.o: no symbols
nm: strnlen.o: no symbols
nm: bmove.o: no symbols
nm: strtoull.o: no symbols
nm: strtoll.o: no symbols
000010d0 T mysql_init

Hij zit er dus wel in.

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Aangezien het static linken van mysqlclient niet lukt wil ik proberen om behalve mysqlclient alles static te linken. Weet iemand met welke switch dat kan?
Mysqlclient moet dus dynamic gelinked worden.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 18:13
Een beetje een gok, maar mik die library file eens direct op de command line? Zoiet sdus: 'gcc -o test /usr/local/lib/libmysqlclient.a <rest van de objects>' (of iets dergelijks).

Het zou in theorie niet uit moeten maken, maar het is al een gekke situatie, dus kan het geen kwaad om zeker te weten welke .a file gebruikt wordt. Als die functies dan gewoon gedefinieerd zijn, zoals uit je nm output blijkt, dan zou ik ook niet meer weten waarom 'ie ze niet zou kunnen linken :? Niet echt een ijzersterke suggestie, maar misschien levert het nieuw inzicht op.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 18:13
Ow wacht eens even; je gebruikt toch niet de C-library onder C++? Geef ook je nm output op je database.o file eens? Als daar inderdaad de mangled versie van mysql_init in voor komt, dan moet je de header files declareren als zijnde C-functies!

C++:
1
2
3
4
extern "C"
{
#include <mysqlclient.h> // of hoe die headers heten...
}


Meestal staat dat echter al wel in de header files zelf (dat kun je ook even checken, natuurlijk), als de maker er bij nagedacht heeft dat de library ook wel eens vanuit C++ gebruikt zou kunnen worden.

[ Voor 26% gewijzigd door Soultaker op 19-06-2003 02:05 ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
code:
1
2
[root@localhost XCC WOL IRC Server]# nm database.o |grep mysql_init
         U mysql_init

Ik gebruik g++, niet gcc. Maar die .a direct op de command line heb ik al geprobeerd en levert hetzelfde resultaat op: undefined reference.

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Ik heb even een minimale versie gemaakt die het probleem bevat.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# cat mysql_test.cpp 
#include <mysql/mysql.h>

int main()
{
        MYSQL h;
        mysql_init(&h);
        return 0;
}
# g++ -lmysqlclient mysql_test.cpp 
# g++ -lmysqlclient -static mysql_test.cpp 
/tmp/ccwpQvKN.o(.text+0x1e): In function `main':
: undefined reference to `mysql_init'
collect2: ld returned 1 exit status
#

Misschien dat iemand dit op zijn machine kan proberen om te kijken of dat wel werkt?
Ik heb het op verschillende RH7 machines, op RH9 en op Debian getest en niks werkt.

[ Voor 28% gewijzigd door Olaf van der Spek op 20-06-2003 14:34 ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Ik kwam hetzelfde probleem weer tegen en het lijkt erop dat de oplossing gevonden is:
code:
1
2
3
4
5
6
7
> g++ mysql_test.c -I../include -L../lib -lmysqlclient -lposix4 -lcrypt -lgen -lsocket -lnsl -lm -lz
> g++ -I../include -L../lib -lmysqlclient -lposix4 -lcrypt -lgen -lsocket -lnsl -lm -lz mysql_test.c
Undefined                       first referenced
 symbol                             in file
mysql_init                          /var/tmp/cc7KoPq7.o
ld: fatal: Symbol referencing errors. No output written to a.out
collect2: ld returned 1 exit status


De eerste regel werkt perfect (geen errors), maar de tweede regel niet, terwijl alleen de volgorde van de parameters anders is. Weet iemand waarom die volgorde uitmaakt?

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 23:06

Creepy

Tactical Espionage Splatterer

GCC(1) GNU Tools GCC(1)

NAME
gcc, g++ - GNU project C and C++ Compiler (gcc-2.95)

SYNOPSIS
gcc [ option | filename ]...
g++ [ option | filename ]...
Zo naar de manpage kijkende zou dat best wel eens het geval kunnen zijn.. maar jij zegt juist dat de eerste regel wel werkt????
Edit: zie onder......


overigens kwam ik dit ook nog tegen:
you need to link to the static libmysqlclient.a instead of libmysqlclient.so.
Unfortunately, gcc chooses the .so file over the .a file if they are both in
the same directory. The easiest workaround is to copy libmysqlclient.a
into /tmp/mysql and add "-L/tmp/mysql -lmysqlclient" to force linking the .a
file.
Edit: en deze ook nog:
A.3.1 Problems When Linking with the MySQL Client Library
If you are linking your program and you get errors for unreferenced symbols that start with mysql_, like the following:

/tmp/ccFKsdPa.o: In function `main':
/tmp/ccFKsdPa.o(.text+0xb): undefined reference to `mysql_init'
/tmp/ccFKsdPa.o(.text+0x31): undefined reference to `mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x57): undefined reference to `mysql_real_connect'
/tmp/ccFKsdPa.o(.text+0x69): undefined reference to `mysql_error'
/tmp/ccFKsdPa.o(.text+0x9a): undefined reference to `mysql_close'

you should be able to solve this by adding -Lpath-to-the-mysql-library -lmysqlclient last on your link line.
Dus de volgorde van file en compiler opties maakt dus blijkbaar uit.

[ Voor 80% gewijzigd door Creepy op 09-09-2004 11:52 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
De .so files staan niet in de lib dir. In gcc.info vond ik wel dit stukje:
`-lLIBRARY'
Search the library named LIBRARY when linking.

It makes a difference where in the command you write this option;
the linker searches processes libraries and object files in the
order they are specified. Thus, `foo.o -lz bar.o' searches
library `z' after file `foo.o' but before `bar.o'. If `bar.o'
refers to functions in `z', those functions may not be loaded.
Begrijpen doe ik het echter niet. Als z voor bar geladen wordt, dan zijn function in z toch juist wel beschikbaar voor bar maar niet voor foo?

[ Voor 89% gewijzigd door Olaf van der Spek op 09-09-2004 13:33 ]


Verwijderd

OlafvdSpek schreef op 09 september 2004 @ 11:52:
Begrijpen doe ik het echter niet. Als z voor bar geladen wordt, dan zijn function in z toch juist wel beschikbaar voor bar maar niet voor foo?
Het linking proces werkt alleen met unresolved references, het onthoudt dus niet elke functienaam in elke objectfile, maar slaat alleen functienamen op die nodig zijn maar nog niet gevonden zijn, als een van die namen aan het einde van het linking proces niet geresolved is, is dat een link error.

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op 09 september 2004 @ 14:47:
Het linking proces werkt alleen met unresoved references, het onthoudt dus niet elke functienaam in elke objectfile, maar slaat alleen functienamen op die nodig zijn maar nog niet gevonden zijn, als een van die namen aan het einde van het linking proces niet geresolved is, is dat een link error.
Maar op het moment dat bar gelinked wordt zijn alle funcies uit z toch bekend?

En wordt linken niet effectief in twee fasen uitgevoerd waardoor de volgorde van de libraries niet uitmaakt?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

OlafvdSpek schreef op 09 september 2004 @ 11:52:
De .so files staan niet in de lib dir. In gcc.info vond ik wel dit stukje:

[...]

Begrijpen doe ik het echter niet. Als z voor bar geladen wordt, dan zijn function in z toch juist wel beschikbaar voor bar maar niet voor foo?
Raar trouwens, de manier hoe gcc er blijkbaar mee omgaat. Wat als je nou 2 libraries hebt met cross-dependencies? Het had veel handiger geweest als ie gewoon continu alle libraries afzoekt op zoek naar nog unresolved external symbols. Op het moment dat bij het includen van een object uit een library weer een nieuwe unresolved symbol geintroduceerd wordt dan kan het zoeken gewoon weer van voor af aan beginnen, net zo lang tot alles is geresolved.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op 09 september 2004 @ 14:53:
Raar trouwens, de manier hoe gcc er blijkbaar mee omgaat. Wat als je nou 2 libraries hebt met cross-dependencies? Het had veel handiger geweest als ie gewoon continu alle libraries afzoekt op zoek naar nog unresolved external symbols. Op het moment dat bij het includen van een object uit een library weer een nieuwe unresolved symbol geintroduceerd wordt dan kan het zoeken gewoon weer van voor af aan beginnen, net zo lang tot alles is geresolved.
Dat is dus vreselijk inefficiënt omdat het in veruit de meeste gevellen niet nodig is. Als er toch cross-dependencies zijn los je dat op door de libraries 2x mee te linken, stel A heeft een functie uit X nodig, X op zijn beurt eentje uit Y, en dan weer Y eentje uit X, dan doe je -lA -lX -lY -lX. Het is dus eenvoudig op te lossen, het komt zelden voor en als het al voorkomt dan is het dubbel specificeren van de libraries in kwestie gegarandeerd efficiënter dan opnieuw alle libraries afzoeken (in een nieuwe linking-pass, multi-pass linkers zijn ondingen imo., veel te traag).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

En waarom is dat dan vreselijk inefficient? Je moet de libs toch wel minstens een keer van voor naar achter scannen op zoek naar symbols, die symbol tables kun je gewoon in een hashmap oid gooien. Bij een volgende unresolved symbol kun je de dus zowat in constante tijd de juiste object file uit de juiste library trekken. Niets inefficients aan. (En in deze tijden is het geheugengebruik nou ook niet bepaald iets om je zorgen over te maken).

VC++ doet het (volgens mij) op een soortgelijke manier, en mijn ervaring is dat die wel een stuk sneller linkt dan g++, en dat terwijl die standaard met een gigantsiche berg aan windows libs linkt.

[ Voor 33% gewijzigd door .oisyn op 09-09-2004 15:19 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op 09 september 2004 @ 15:15:
En waarom is dat dan vreselijk inefficient? Je moet de libs toch wel minstens een keer van voor naar achter scannen op zoek naar symbols, die symbol tables kun je gewoon in een hashmap oid gooien.
Accoord, maar je hebt het dan niet meer over een klassieke multi-pass linker. Normaal werkt een linker alleen met unresolved references, zijn er na het beëindigen van een pass nog unresolved symbols dan doorloopt een multi-pass linker opnieuw het proces van libraries doorzoeken in een volgende pass, zo lang totdat er geen unresolved symbols meer zijn. Als je bij een multipass linker dus (moedwillig) x libraries in precies de verkeerde volgorde specificeert, dan vergt de link x passes.

Jij hebt het nu over het afruilen van tijdcomplexiteit tegen ruimtecomplexiteit, door elk (global) symbol dat je tegen komt op te slaan, of er nu aan gerefereerd wordt of niet. Dat levert dus een snelheid in de zelfde orde van grootte als een single-pass linker op, tegen een naar schatting 4x zo grote symbol table (volgens de 20-80 regel, gemiddeld wordt maar 20% van de symbols die een interface beschikbaar stelt gebruikt). Tot voor kort waren zulke grote symbol tables gewoon not-done, tegenwoordig is minder een ruimte-probleem als wel een filosofische kwestie (compilen is al zo'n vreselijke load-hog geworden, moet dat nu met de linker ook?)
VC++ doet het (volgens mij) op een soortgelijke manier, en mijn ervaring is dat die wel een stuk sneller linkt dan g++, en dat terwijl die standaard met een gigantsiche berg aan windows libs linkt.
C++ linken met g++ is traag omdat er een extra collect-pass tussen de compiler en de linker zit die kijkt welke standaard C++ libs er meegelinkt moeten worden (helaas). Je kunt dat overigens voorkomen door enkel naar objects te compilen en die objects handmatig met de juiste standaard libs te linken (met ld ipv. g++).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op 09 september 2004 @ 15:50:
[...]


Accoord, maar je hebt het dan niet meer over een klassieke multi-pass linker. Normaal werkt een linker alleen met unresolved references, zijn er na het beëindigen van een pass nog unresolved symbols dan doorloopt een multi-pass linker opnieuw het proces van libraries doorzoeken in een volgende pass, zo lang totdat er geen unresolved symbols meer zijn. Als je bij een multipass linker dus (moedwillig) x libraries in precies de verkeerde volgorde specificeert, dan vergt de link x passes.

Jij hebt het nu over het afruilen van tijdcomplexiteit tegen ruimtecomplexiteit, door elk (global) symbol dat je tegen komt op te slaan, of er nu aan gerefereerd wordt of niet. Dat levert dus een snelheid in de zelfde orde van grootte als een single-pass linker op, tegen een naar schatting 4x zo grote symbol table (volgens de 20-80 regel, gemiddeld wordt maar 20% van de symbols die een interface beschikbaar stelt gebruikt). Tot voor kort waren zulke grote symbol tables gewoon not-done, tegenwoordig is minder een ruimte-probleem als wel een filosofische kwestie (compilen is al zo'n vreselijke load-hog geworden, moet dat nu met de linker ook?)
Heb je een linkje om dit te onderbouwen, want ik geloof eerlijk gezegd niet dat het daadwerkelijk zo'n grote impact heeft om de symbol tables in het geheugen te laten. Je zult een symbol table van een library sowieso moeten uitlezen om te kijken of het symbol waarnaar je zoekt toevallig in die library zit. Je kunt die table net zo goed gewoon in het geheugen laten als je vervolgens verder gaat met andere libraries.

Ik heb het even gecontroleerd, de symbol table van de multithreaded debug c-runtime (de grootste lib hier) die bij VC++ zit heeft een symbol table van "slechts" 450kb. En dan praat je over een enorme library. Stel dat een gemiddelde lib 200k is, dan kun je nog met gemak tientallen libs in het geheugen houden zonder dat dat enorm veel geheugen inneemt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op 09 september 2004 @ 16:25:
Ik heb het even gecontroleerd, de symbol table van de multithreaded debug c-runtime (de grootste lib hier) die bij VC++ zit heeft een symbol table van "slechts" 450kb. En dan praat je over een enorme library. Stel dat een gemiddelde lib 200k is, dan kun je nog met gemak tientallen libs in het geheugen houden zonder dat dat enorm veel geheugen inneemt.
Een symbol table van 450kB was een jaar of 15 geleden nog een onding (ld is ouder), drie symbol tables van 200kB elk was al een drama (aangenomen dat ze in ram evenveel kosten als in de object file), tegenwoordig is er idd. (zoals ik al zei) geen ruimte-probleem meer, maar waarom zoveel ruimte gebruiken als het onnodig is (in veruit de meeste gevallen zijn er geen cross references en volstaat een "domme" single-pass linker).

Ik zal eens een linkje naar de 20-80 regel voor API's zoeken (dat was een vuistregel die ik ooit tijdens mijn opleiding geleerd heb, zo'n 2o jaar geleden).
Pagina: 1