2009-09-27 14 views
13

Mam program (w szczególności mój wpis dla SO DevDays Countdown app challenge), która opiera się na kilku dynamicznych bibliotek, a mianowicie libSDL, libSDL_ttf i innych. Mam zainstalowane te biblioteki pod /opt/local/lib przez MacPorts, a wiele osób nie będzie ich zainstalowanych (a niektóre mogą je zainstalować, ale nie w tej lokalizacji).Jak rozpowszechniać system Mac OS X za pomocą bibliotek zależnych?

Jak mogę dystrybuować swój program tak, że ludzie bez tych bibliotek zainstalowanych można uruchomić go out-of-the-box? Oczywiście będę musiał rozpowszechniać różne pliki .dylib, ale wykonanie tego jest niewystarczające. Program ładujący dynamicznie szuka bibliotek zainstalowanych w lokalizacjach, w których je zainstalowano. Czy istnieje sposób na powiedzenie dynamicznemu programowi ładującemu, aby szukał w bieżącym katalogu pliku wykonywalnego, na przykład, co system Windows robi z bibliotekami DLL? Ludzie nie powinni modyfikować żadnych zmiennych środowiskowych (np. DYLD_LIBRARY_PATH), ponieważ znowu chcę, aby to działało natychmiast po uruchomieniu.

Odpowiedz

5

Jak wspomniano nie używasz Xcode, więc jest to trochę trudne. Oto opcje według moich preferencji:

  1. Przełącz na Xcode. Użyj frameworków. Biblioteki SDL są już dostępne jako frameworki i widziałem więcej niż kilka gier komercyjnych z biblioteką libsdl.framework w pakiecie aplikacji.

  2. Użyj ramy, ale zachować swój Makefile. Pobierz wersje szkieletowe swoich bibliotek SDL (lub zbuduj je samodzielnie) i połącz je z flagą -framework linker. Rozłóż frameworki za pomocą aplikacji lub nie, i powiedz użytkownikom, aby umieścili je w katalogu ~/Library/Frameworks lub w/Library/Frameworks. Nie zawracałbym sobie głowy instalatorem.

  3. Statyczne połączenie z SDL. W Makefile będziesz musiał podać ścieżkę statycznych bibliotek zamiast używać flagi -l, np. Uruchamiasz "lb blah blah /opt/local/lib/libsdl.a". Nie ma sposobu, żebym wiedział, że wolałbym statyczne w stosunku do bibliotek współdzielonych i uwierz mi, szukałem.

+0

Po przemyśleniu tego, myślę, że po prostu pójdę ze statycznym łączeniem w celu dystrybucji. Jeśli mam zamiar rozpowszechniać biblioteki dynamiczne w każdym razie, to pokonuje kilka celów ich używania, więc równie dobrze mógłbym uniknąć bólu związanego z ładowaniem dynamicznym. –

+1

4. Korzystając z opcji 2. powyżej, umieść frameworki wewnątrz swojego pakietu .app (plik .dmg) i zmień wymagania dotyczące plików wykonywalnych za pomocą polecenia install_name_tool. Oto kilka przykładów użycia parametru install_name_tool: http://qt-project.org/doc/qt-4.8/deployment-mac.html. Dietrich, czy mógłbyś włączyć to do swojej odpowiedzi? –

+0

@ MilanBabuškov: Wygląda na to, że zostało to już uwzględnione w poniższej odpowiedzi. Nie widzę potrzeby duplikowania informacji. –

3

Statycznie połączyć biblioteki.

+0

Tyle za ponowne użycie kodu. –

+6

Statycznie połączone biblioteki są traktowane jako "ponowne wykorzystanie kodu", ponieważ kod biblioteki musi być zapisany/przetestowany/debugowany tylko raz, bez względu na to, ile aplikacji będzie z niego korzystać. Chociaż prawdą jest, że wiele kopii skompilowanego kodu może znaleźć się na dysku użytkownika, nie jest to tak duży problem jak kiedyś, ponieważ dyski twarde są tak duże. –

13

Podstawowe podejście do tego celu jest wysłać je w wiązki .app. Następnie zmodyfikujesz lokalizację, w której linker szuka bibliotek współdzielonych, aby to uwzględnić.

Kroki są:

  1. utworzyć nowy kopiowanie plików zbudować fazy do celu, który kopiuje te pliki do katalogu ramach pakietu .app.

  2. Edycja konfiguracji kompilacji ustawienie „Runpath ścieżek wyszukiwania” obejmuje @executable_path/../Frameworks

Jeżeli budujesz swój plik wykonywalny z tych zmian, a następnie patrzeć, należy uznać, że dylibs istnieje w katalogu Foo.app/Contents/Framework i biegania otool -L Foo.app/Contents/MacOS/Foo powinno się wydawać i wpisywać przedrostek @rpath dla tych dylibs.

Z tego Cocoabuilder post:

Ogólnie @loader_path jest korzystniejszy @executable_path, ponieważ
umożliwia osadzony ramy do pracy zarówno w pliku wykonywalnego, a wiązki,
wtyczek lub nośnej. Jedynym minusem jest to, że @loader_path
wymaga 10.4 lub nowszej. Jeśli jesteś na 10.5 lub nowszym, @rpath jest nawet
lepiej niż @loader_path.

+0

Nie używam Xcode (bez pakietu .app), wystarczy zwykły gcc i make. Używam także OS X 10.4; zgodnie z http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/RunpathDependentLibraries.html, ścieżki przeszukiwania runpath są obsługiwane tylko w wersji 10.5 i nowszej. –

+1

Wierzę, że @executable_path będzie działać nawet na 10.4 (@loader_path i @rpath nie będą). Możesz również przeczytać: http://blog.onesadcookie.com/2008/01/installname-magic.html – nall

+0

Jeśli nie korzystasz z Xcode, najlepszym rozwiązaniem może być użycie Autotools i znajomych. –