2012-11-02 11 views
26

Nie mogę być jedyną osobą, która do tego dołączy.Jak mogę połączyć (lub obejść) dwie statyczne biblioteki stron trzecich, które definiują te same symbole?

Mam aplikację C++, która musi łączyć się z jedną stroną trzecią i inną biblioteką statyczną w zestawie SDK. SDK, z jakiegoś ohydnie frustrującego powodu, zrekompilował podzbiór tej samej biblioteki trzeciej strony do swojej własnej (przemianowanej) biblioteki lib, chociaż same symbole są nazywane tymi samymi i nie są enkapsulowane w przestrzeni nazw. Moja aplikacja zależy od tej samej biblioteki strony trzeciej.

Rozważałem kilka opcji, ale może czegoś brakuje i mam nadzieję, że świeży wygląd pomoże mi. Być może jestem blisko i ktoś będzie znał następny krok dla jednego z nich. Wymienię to, co próbowałem, i niedociągnięcia każdego z rozwiązań do tej pory:

  1. Łącze z oboma. Otrzymuję około 2500 linii definicji redefinition/size change ostrzeżenia i błędy. Wtedy po raz pierwszy odkryłem, że zdefiniowali te same symbole. Próbuję przekompilować OpenSSL za pomocą g ++ i przenieść go do przestrzeni nazw ... zobacz edycję poniżej ...

  2. Łącze tylko z SDK. Dostaję niezdefiniowane symbole, od których zależy mój własny kod - wtedy odkryłem, że ich rekompilacja z biblioteki trzeciej jest podzbiorem, lub przynajmniej została skonfigurowana z wyłączonym jednym modułem.

  3. Łącze z biblioteką tylko dla osób trzecich. Mam kilka niezdefiniowanych symboli zgłoszonych przez SDK - jeden z nich jest faktycznie #define w pliku nagłówkowym w ramach biblioteki trzeciej strony, więc wszystkie odniesienia w bibliotece trzeciej strony definiują definicję, ale odniesienia poza nią nie . Przeniosłem to do pliku c, który to rozwiązuje, jednak wciąż mam dwie nierozwiązane funkcje, których nigdzie nie mogę znaleźć. To jest najbliżej, jak do tej pory.

  4. Wykasuj symbole konfliktów z jednej biblioteki i łącza w obu. Do tej pory to nie zadziałało. Może to być problem związany z wersją między statycznie połączoną biblioteką SDK a wersjami, w których próbowałem używać biblioteki stron trzecich, ale wygląda na to, że niektóre funkcje zostały przeniesione między symbolami, więc usuwając symbol, nieumyślnie usuwam funkcja, której potrzebuję gdzie indziej. Nie ma idealnego odwzorowania między funkcjami symboli w SDK a funkcjami symboli w lib innej firmy. Czy można usuwać funkcje bez konieczności ręcznego dostosowywania adresów?

Byłem badając symbole w libs z:

nm -C --defined-only lib<name>.a 

i wydobycia całych obiektów z:

ar -x lib<name>.a <objname>.o 

Mam nadzieję, że będzie to również pomóc innym, którzy musieli połączyć z trzecią -plików-stron, które są ze sobą sprzeczne. Ze względu na specyfikę, lib strony trzeciej to OpenSSL, a SDK to Opsec - libcpopenssl.a jest szkodliwą biblioteką w Opsec.

** EDYCJA - Możliwe późniejsze obejście może polegać na przekompilowaniu OpenSSL za pomocą g ++ i umieszczeniu całej rzeczy w przestrzeni nazw, a następnie połączeniu obu bibliotek. Próbuję tego teraz ... jeszcze przed ...

+0

Czy możesz zostawić * out * pochodną opsec openssl i połączyć OpenSSL? Wygląda na to, że zawiera libcopopenssl.a na wypadek, gdyby nie było połączenia z OpenSSL. Symbole powinny się łączyć, jeśli poprawnie dzielą pochodną OpenSSL. To znaczy. łącz wszystkie inne elementy w swoim zestawie lib * z wyjątkiem * tej biblioteki i połącz zamiast niej OpenSSL. – WhozCraig

+0

To właśnie próbowałem w punkcie 3 powyżej, zasadniczo. Musiałem przenieść # definicję do pliku C i zrekompilować, a następnie miałem jeszcze dwa nieokreślone symbole. Nie mogę znaleźć SSL_get_peer_dh lub DH_dup w dowolnym miejscu. – rutgersmike

+0

Nie można napisać z 'nm', aby pobrać symbole z * dobrego * OpenSSL. Następnie usuń * bad * lib z tej listy nazw. Jeśli są połączone statycznie, wewnętrzne odwołania są już rozstrzygnięte. Lub jeśli nie, użyj '-r' lub' -Ur' do linkera. –

Odpowiedz

3

Wyszukiwarka Google wskazuje, że SSL_get_peer_dh i DH_dup są naprawdę dodatkami z libcpopenssl.a i nie istnieją one również w mojej kopii OpenSSL.Więc naprawdę musisz powiązać tę bibliotekę. Łączenie obu bibliotek razem (Podejście 4 powyżej) na poziomie binarnym raczej nie zadziała - OpenSSL jest bardzo wrażliwy na swój ABI (zwykle mają one .so pliki podzielone na mniejsze numery), więc musiałbyś mieć dużo szczęścia, aby mieć .so, który jest zgodny z ABI dla ich plików .a.

Moja sugestia to odmiana podejścia 4, ale na poziomie źródłowym: będziesz mieć link w Opsec libcpopenssl.a, ponieważ jest to zmodyfikowana wersja OpenSSL, która zawiera dodatkowe symbole (i ewentualnie inne modyfikacje) i chwyć dodatkowe funkcje, których potrzebujesz ze źródeł OpenSSL i przekompiluj te obiekty za pomocą libcpopenssl.a, aby mogły korzystać z funkcji z wersji Opsec. Jeśli używasz tylko kilku funkcji OpenSSL, które nie są eksportowane przez libcpopenssl.a, jest to całkiem wykonalne.

To wciąż uciążliwe podejście, ale jest to gwarantowany sposób na uzyskanie kompatybilności symboli, pod warunkiem oczywiście, że SDK Opsec nie wprowadził semantycznych zmian w OpenSSL, które złamią dodatkowe funkcje OpenSSL, które wciągają Twój projekt.

(Jestem nowy w StackOverflow, więc nie wiem, czy ta sugestia kwalifikuje się jako właściwa odpowiedź, ale nie mam punktów reputacji, aby dodawać komentarze. Tak, usuniemy to, jeśli jest niewłaściwe.)

+0

Nie mogłem znaleźć wiele na temat tych funkcji, dzięki! Zmęczyłem się modellingiem OpenSSL, ale w pewnym sensie mam zamiar go skompilować do wersji C++ i przenieść do przestrzeni nazw. Zaktualizuję, gdy będę mieć więcej informacji. – rutgersmike

1

Jeśli jesteś chorobliwie ciekawy, 249 plików zostało zmodyfikowanych w najnowszej wersji OpenSSL, aby go skompilować. Najczęstszą kwestią była zdecydowanie obfitość rzutów w stylu C, szczególnie w przypadku void *. Teraz widzę "reinterpret_cast" w moich snach.

To jednak nie rozwiązało go samemu - nadal musi zostać umieszczone w przestrzeni nazw w całości, co oznacza modyfikację wszystkich plików ponownie, jak również własnych wewnętrznych odniesień do niego. Myślę, że na razie mam zamiar to przekazać.

Dzięki za pomoc dla wszystkich.