Kiedy powinniśmy używać „osadzonych plików binarnych” zamiast „połączonych struktur” w Xcode?

140

Jest dobre pytanie o różnicę między tymi dwiema opcjami, jak opisano w sekcji Łączenie pliku binarnego z bibliotekami a struktury osadzania .

Wygląda na to, że mamy opcje, aby używać ich obu, tylko zastanawiam się, w którym przypadku powinniśmy lepiej używać osadzonych plików binarnych, czy raczej niż połączonego frameworka?

Jakieś solidne przykłady, które pozwolą lepiej rozwiązać ten problem? Dzięki

Forrest
źródło
Możliwy duplikat
pliku

Odpowiedzi:

239

Pytanie, które utworzyłeś, odnosi się do funkcji „Połącz plik binarny z bibliotekami”, która różni się nieco od osadzonego pliku binarnego.

„Połącz plik binarny z bibliotekami” oznacza to, czego można oczekiwać w odniesieniu do łączenia: bez względu na to, czy plik binarny jest biblioteką statyczną, biblioteką dynamiczną czy frameworkiem, zostanie połączony z kodem obiektowym w czasie łączenia po kompilacji.

Kiedy myślisz o połączeniu z biblioteką statyczną, to, co się dzieje, jest całkiem jasne: linker kopiuje kod z biblioteki (np. libFoo.a) Do wyjściowego pliku binarnego. Twój plik wyjściowy rośnie, ale nie musi rozwiązywać żadnych zewnętrznych zależności w czasie wykonywania. Wszystko, czego program potrzebuje do uruchomienia (w odniesieniu do biblioteki statycznej), jest obecne po jego zbudowaniu.

W przypadku biblioteki dynamicznej (.dylib lub frameworku dostarczonego przez system) oczekuje się, że biblioteka, z którą się łączysz, będzie znajdować się gdzieś w ścieżce systemu ładującego bibliotek dynamicznych podczas uruchamiania programu. W ten sposób nie masz narzutu kopiowania wszystkich zewnętrznych bibliotek stron trzecich do swojego pliku binarnego, a wszystkie różne programy na komputerze, które również łączą się z tą biblioteką, będą w stanie ją znaleźć, co oszczędza minimalnie miejsce na dysku, ale także potencjalnie miejsce w pamięci, w zależności od tego, jak i gdzie system buforuje biblioteki.

Framework jest bardzo podobny do biblioteki dynamicznej, ale może zawierać zasoby w swojej strukturze katalogów (obrazy, audio, inne frameworki itp.). W tym przypadku prosty statyczny Biblioteka lub .dylib plik nie będzie go wyciąć, więc może trzeba linku do ramy tak , że można znaleźć to, czego potrzebuje, aby działać prawidłowo.

Kiedy łączysz się z platformą zewnętrzną (powiedz coś, co pobrałeś z github i zbudowałeś samodzielnie), może nie być obecny w systemie, na którym zamierzasz działać. W takim przypadku nie tylko utworzyłbyś link do frameworka, ale również osadziłbyś go w pakiecie aplikacji, korzystając z fazy „Kopiuj struktury”. Gdy program jest uruchomiony, konsolidator środowiska wykonawczego (inaczej resolver) zajrzy do pakietu oprócz ścieżki programu ładującego system, znajdzie osadzoną strukturę i połączy ją, aby aplikacja miała kod potrzebny do uruchomienia.

Wreszcie, to, co właściwie jest „osadzonym plikiem binarnym”, to plik wykonywalny, który zarówno osadzasz w pakiecie aplikacji za pośrednictwem fazy kopiowania plików, jak i wykonujesz samodzielnie, być może za pomocą wywołania popen()lub podobnego. Osadzony plik binarny może zostać wywołany przez Twój program, ale nie jest z nim powiązany. Jest to w pełni zewnętrzna jednostka (podobnie jak programy w /binkatalogu).

W praktyce w przypadku bibliotek i frameworków dostarczonych przez system będziesz łączył się z nimi i to wszystko, co musisz zrobić.

Jeśli chcesz połączyć zbudowaną przez siebie bibliotekę, która nie wymaga żadnych zasobów osadzonych (tj. Nie wymaga istnienia struktury), możesz po prostu połączyć się z biblioteką statyczną. Jeśli zauważysz, że masz wiele modułów w swoim programie, które chcą używać tego samego kodu biblioteki, przekonwertowanie go na strukturę lub bibliotekę dynamiczną i połączenie z nimi może zaoszczędzić miejsce i może być wygodne (szczególnie jeśli problemem jest użycie pamięci).

Wreszcie, frameworki mogą zawierać nie tylko zasoby, ale także pliki nagłówkowe i / lub licencyjne. Używanie frameworka do przenoszenia tych plików jest w rzeczywistości wygodnym mechanizmem dystrybucji, więc często możesz chcieć włączyć framework tylko po to, aby te rzeczy mogły tagować wraz z twoim plikiem binarnym (tj. Wymagania licencyjne mogą uczynić to obowiązkowym).

--- EDYTOWAĆ ---

Adam Johns opublikował następujące pytanie jako komentarz:

To świetna odpowiedź. Jest jednak coś, w czym wciąż jestem trochę zdezorientowany. Co to znaczy samemu wykonać plik binarny? Czy masz na myśli po prostu użycie kodu osadzonej platformy? Wiem, że wspomniałeś o popen (), ale mówisz, że moja aplikacja wywołuje popen ()? Naprawdę nie wiem, co to znaczy.

Mówię, że osadzony plik binarny to po prostu kolejny plik zasobów w twoim pakiecie, taki jak plik audio lub obraz, chociaż plik jest zamiast tego wykonywalnym narzędziem wiersza poleceń. popen()Function ( man popenod terminala, aby przeczytać więcej o tym) pozwala na wykonywanie dowolnych programów z innego uruchomionego programu. system()Funkcja jest inna droga. Są inne i podam tutaj historyczny przykład, który może sprawić, że zrozumienie użycia osadzonego pliku binarnego będzie nieco bardziej przejrzyste:

Jak zapewne wiesz, po uruchomieniu aplikacji w systemie Mac OS X jest ona uruchamiana z identyfikatorem bieżącego użytkownika. W większości typowych instalacji jest to domyślny użytkownik na pulpicie admin, któremu nadawany jest identyfikator użytkownika 501.

W systemach operacyjnych opartych na Uniksie tylko rootużytkownik (identyfikator użytkownika 0) ma pełny dostęp do całego systemu plików. Czasami zdarza się, że program instalacyjny uruchamiany przez użytkownika Pulpitu musi zainstalować pliki w uprzywilejowanym katalogu (na przykład sterowniki). W takim przypadku aplikacja musi przekazać swoje uprawnienia rootużytkownikowi, aby mógł pisać w tych zastrzeżonych katalogach.

Aby ułatwić to w systemach operacyjnych za pośrednictwem OS X 10.7, firma Apple udostępniła w swoim interfejsie API usług autoryzacyjnych funkcję AuthorizationExecuteWithPrivileges () (jest to obecnie przestarzałe, ale nadal stanowi użyteczny przykład).

AuthorizationExecuteWithPrivileges()jako argument wziął ścieżkę do narzędzia wiersza poleceń do wykonania jako root. Narzędziem wiersza poleceń był wykonywalny skrypt powłoki lub skompilowany plik binarny napisany w celu uruchomienia logiki instalacji. To narzędzie zostało zainstalowane w pakiecie aplikacji, tak jak każdy inny plik zasobów.

Po wywołaniu system operacyjny wyświetli okno dialogowe autoryzacji z prośbą o podanie hasła użytkownika (widzieliście to już wcześniej!), A po wprowadzeniu uruchomi program rootw imieniu Twojej aplikacji. Ten proces jest podobny do zwykłego wykonania programu ze popen()sobą, chociaż popen()sam nie daje korzyści z eskalacji uprawnień.

par
źródło
62
Skąd znasz te rzeczy?
Ian Warburton,
56
@IanWarburton Programuję systemy operacyjne Apple od ponad 20 lat i tu i ówdzie zebrałem kilka ciekawostek. :)
par
1
@JustAMartin Mam na myśli link, ale masz rację, że musisz go również osadzić w fazie kopiowania plików (w przeciwnym razie jak byś go użył?). Celem korzystania z platformy zewnętrznej lub osadzonego pliku binarnego jest wykonanie kodu dostarczonego przez jednostkę. W przypadku osadzonego pliku binarnego nie jest wymagane łączenie. W czasie wykonywania konstruujesz ścieżkę do pliku binarnego, a następnie ręcznie go uruchamiasz. W przypadku frameworka konsolidator czasu kompilacji połączy go podczas budowania aplikacji, a następnie (jeśli jest to framework innej firmy) osadza go w fazie kopiowania plików, a na końcu konsolidator środowiska uruchomieniowego łączy go ponownie po uruchomieniu aplikacji .
par
1
Nie jest jasne, na co odpowiedziałeś @JustAMartin. Celem korzystania z platformy zewnętrznej lub osadzonego pliku binarnego jest wykonanie kodu dostarczonego przez jednostkę. Obecnie wbudowane pliki binarne mogą być również platformami zewnętrznymi. Próbuję zrozumieć, co masz na myśli ... AFA Rozumiem, wbudowane pliki binarne oznaczają, oddzielny plik binarny osadzonego frameworka zostanie wprowadzony do pakietu aplikacji, a jeśli po prostu połączysz ten sam framework, umieściłby go w tym samym pliku binarnym co że z aplikacji. Proszę mnie poprawić, jeśli się mylę ...
hariszaman
1
Może jest nowa magia Xcode, która załaduje osadzony framework. Minęło trochę czasu, odkąd potrzebowałem tej funkcjonalności. Jeśli chcesz dowiedzieć się, co się dzieje więcej, napisz nowe pytanie tutaj na SO.
par
35

W skrócie,

  • biblioteki systemowe, połącz je;
  • Biblioteki innych firm, osadzaj je.

czemu?

  • jeśli spróbujesz osadzić biblioteki systemowe, nie znajdziesz ich na liście podręcznej;
  • jeśli połączysz biblioteki innych firm, prawdopodobnie nastąpi awaria.
Świetlana przyszłość
źródło
7

Jest częścią Dependencyzarządzania [Informacje]

Należy pamiętać, że Xcode 11zawiera tylko Frameworks, Libraries, and Embedded Contentsekcję w Generalzakładce

Link binarny

Build Phases -> Link Binary With Librariesjest lustrem General -> Linked Frameworks and Libraries.

Biblioteka statyczna i struktura

Jeśli dodasz Static Library or Static Frameworkdo tej sekcji, pojawi się ona w Frameworks grupie [About] ( Project Navigator -> <workspace/project> -> Frameworks) i zostanie dodana referencja do twojego projektu. Wtedy będzie używany przez Static Linker. Static Linkerw czasie kompilacji włączy / skopiuje cały kod z biblioteki do wykonywalnego pliku obiektowego. Static linkerdziała w połączeniu zBuild Settings -> <Library/Framework> Search Paths

Static Library

Static Framework

  • Build Settings -> Framework Search Paths. Jeśli nie dodasz static frameworkdo tej sekcji, otrzymasz błąd kompilacji [Nie ma takiego modułu]

Osadź plik binarny

Biblioteka statyczna i struktura statyczna

Osadzanie nie miałoby żadnego sensu dla a Static Libraryi Static Frameworkponieważ symbole z nich są kompilowane do wykonywalnego pliku binarnego. Xcode nie pozwoli ci upuścić a static libraryw sekcji Osadzanie.

Dynamiczna struktura

Build Phases -> Embed Frameworksjest lustrem General -> Embedded Binaries. Osadzenie faktycznie dodaje kopię struktury do pakietu aplikacji. W rezultacie, kiedy framework zostanie dodany / usunięty z Embedsekcji, zostanie automatycznie dodany / usunięty z Linkedsekcji. Domyślnie folder pakietu to, Frameworksale możesz go zmienić za pomocą Destinationpola. Ponadto możesz określić plik Subpath.

Dynamic linker :dyldprzy ładowaniu lub w czasie wykonywania spróbuje znaleźć osadzoną strukturę za pomocą @rpath[Informacje] Jeśli nie zostanie znaleziona, wystąpi błąd [dyld: Biblioteka nie została załadowana]

[W przypadku korzystania z łącza i umieszczania]

[Słownictwo]

yoAlex5
źródło