2011-09-27 6 views
16

Stworzyłem nową frameworkę kakao w Xcode, usunąłem wszystkie biblioteki i pliki, które ona zawiera na początku oprócz plików pomocniczych.Jak utworzyć działające środowisko z plikami dylib w Xcode 4

mam 2 pliki:

add.h 

#ifndef add_add_h 
#define add_add_h 

void add(void); 

#endif 

i

add.c 
#include <stdio.h> 
#include "add.h" 

void add(void) 
{ 
    printf("adfding"); 

} 

etapami kompilacji I dodają add.c skompilować źródła i add.h kompilacji nagłówków publicznych. Projekt budowany jest bez problemu, ale w jego strukturze nie ma pliku dylib, a kiedy przeciągam i upuszczam framework do innego projektu, mówi on, że nie można znaleźć pliku dylib.

dyld: Library not loaded: @rpath/add.framework/Versions/A/add 
    Referenced from: /Users/vjoukov/Desktop/Projects/test/build/Debug/test.app/Contents/MacOS/test 
    Reason: image not found 

Jak mogę utworzyć prostą strukturę i przechowywać w niej pliki dylib?

Odpowiedz

61

Myślę, że nie rozumiesz komunikatu o błędzie.

A A .framework działa jako biblioteka dynamiczna, ale w folderze .framework nie będzie żadnego możliwego do załadowania pliku obiektu Mach-O z rzeczywistym rozszerzeniem nazwy pliku .dylib.

Istnieje kilka powodów, dla których może pojawić się komunikat o błędzie z dyld, programu ładującego biblioteki dynamiczne, w czasie wykonywania. Po pierwsze zapomniałeś skopiować .frameworks do zbudowanego pakietu aplikacji podczas procesu budowania. Chociaż można je skopiować do dowolnej lokalizacji w pakiecie aplikacji, tradycyjne miejsce znajduje się w AppName.app/Contents/Frameworks/. Jeśli jeszcze tego nie zrobiłeś, wybierz kolejno opcje Project> New Build Phase> New Copy Build Build Phase. Zmień okno podręczne Destination na Frameworks, jak na poniższym obrazku.

enter image description here

Będziesz następnie przeciągnij ikonę ram do folderu tak, że to skopiowane podczas procesu kompilacji.

enter image description here

Druga i bardziej prawdopodobną przyczyną ramy nie można znaleźć w czasie wykonywania jest to, że nie określono żadnych ścieżek wyszukiwania runpath do głównego pliku wykonywalnego. (Jest to potrzebne, ponieważ, jak widzieliśmy z komunikatu o błędzie, twoja architektura została zbudowana przy użyciu nowszej nazwy w stylu instalacji @rpath/ (@rpath/add.framework/Versions/A/add) niż starszych stylów @executable_path/ lub @loader_path/).

Pod warunkiem, że kopia ram niestandardowych do położenia wymienionego powyżej, by dodać wpis runpath wyszukiwania ścieżki @loader_path/../Frameworks, jak pokazano na rysunku poniżej:

enter image description here

Poniższy fragment, który wyjaśnia, w jaki sposób biblioteki dynamiczne występują w czasie wykonywania jest z podręcznika z dyld:

DYNAMIC ładowaniem bibliotek

W przeciwieństwie do wielu innych systemów operacyjnych, Darwin nie lokalizuje zależnych bibliotek dynamicznych za pomocą swojej nazwy pliku liści. Zamiast tego stosuje się pełną ścieżkę do każdego z dyb (011). /usr/lib/libSystem.B.dylib). Ale są chwile, kiedy pełna ścieżka nie jest właściwa; na przykład może chcieć, aby twoje pliki binarne były instalowane w dowolnym miejscu na dysku. Aby to wspierać, istnieją trzy zmienne, które mogą być używane jako prefiks ścieżki. W środowisku wykonawczym dyld zastępuje dynamicznie generowaną ścieżkę dla prefiksu @xxx/.

@executable_path/

Zmienna ta jest zastępowana ścieżką do katalogu zawierającej główny plik wykonywalny dla procesu. Jest to użyteczne przy ładowaniu dylibs/frameworks osadzonych w katalogu .app. Jeśli główny plik wykonywalny jest /some/path/My.app/Contents/MacOS/My i plik ramy dylib jest
/some/path/My.app/Contents/Frameworks/Foo.framework/Versions/A/Foo, następnie ścieżka obciążenie ramy może być zakodowany jako @executable_path/../Frameworks/Foo.framework/Versions/A/Foo a katalog .app mógłby być przesuwane w systemie plików i dyld nadal będzie mógł załadować osadzoną strukturę.

@loader_path/

zmienna jest zastąpiony ścieżce katalogu zawierającego Mach-O binarny zawierający polecenie obciążenia za pomocą @loader_path. Tak więc, w każdym pliku binarnym @loader_path rozwiązuje się na inną ścieżkę, podczas gdy @executable_path zawsze znajduje się na tej samej ścieżce co . @loader_path jest użyteczny jako ścieżka ładowania dla partycji/dylib osadzonej we wtyczce, jeśli ostateczny system plików lokalizacja wtyczki nieznanej (nie można użyć ścieżek bezwzględnych) lub jeśli używana jest wtyczka przez wiele aplikacji (nie można więc użyć @executable_path). Jeżeli wtyczka Mach-O pliku jest /some/path/Myfilter.plugin/Contents/MacOS/Myfilter i plik dylib ramy jest /some/path/Myfilter.plugin/Contents/Frameworks/Foo.framework/Versions/A/Foo, czym ścieżki obciążenia ramy może być kodowany jako @loader_path/../Frameworks/Foo.framework/Versions/A/Foo i katalogu Myfilter.plugin może być przemieszczać w pliku system i dyld nadal będą w stanie ładować osadzoną strukturę.

@rpath/

dyld utrzymuje bieżący stos ścieżek nazywa się ścieżką run lista. Po napotkaniu @rpath jest on zastępowany przez każdą ścieżkę na liście ścieżek przebiegu, aż do znalezienia możliwego do załadowania dylib. Stos ścieżek przebiegu zbudowany jest z komend ładujących LC_RPATH w łańcuchu zależności, które prowadzą do bieżącego obciążenia dylib. Można dodać dodać polecenie ładowania LC_RPATH do obrazu z opcją do ld (1). Można nawet dodać ścieżkę komendy ładowania obciążenia LC_RPATH, która rozpoczyna się od @loader_path/, a następnie przesunie ścieżkę na stosie ścieżek, która jest relatywna do obrazu zawierającego obraz . Korzystanie z @rpath jest najbardziej przydatne, gdy masz skomplikowaną strukturę katalogów programów i dylibs, która może być zainstalowana w dowolnym miejscu, ale zachowaj ich względne pozycje. Scenariusz można zaimplementować przy użyciu @loader_path, ale każdy klient jednostki dylib może wymagać innej ścieżki ładowania, ponieważ jego względna pozycja w systemie plików jest inna. Użycie poziomu @rpath wprowadza poziom dwukierunkowości, który upraszcza rzeczy. You wybierz lokalizację w strukturze katalogów jako punkt kontrolny. Każdy dylib otrzymuje ścieżkę instalacji rozpoczynającą się od @rpath iścieżką do dylib względem punktu kontrolnego. Każdy główny plik wykonywalny jest połączony z -rpath @loader_path/zzz, gdzie zzz jest ścieżką z pliku wykonywalnego do punktu kontrolnego. W środowisku wykonawczym dyld ustawia ścieżkę uruchamiania jako punkt kontrolny, a następnie każdy z nich jest znaleziony względem punktu kontrolnego.

+5

WOW! To jeden z kompletnych odpowiedzi, rozwiązał również problem, który miałem! Dzięki!! –

+0

Bardzo dokładna i kompletna odpowiedź ... Dobra robota! –

+0

Doskonała odpowiedź! Nigdy nie wiedziałem, jak działają dyeks. Miły! – JackPearse