Esistono due modi per creare un app bundle su MacOSX, Easy e the Ugly.
Il modo più semplice è usare XCode. Fatto.
Il problema è che a volte non puoi.
Nel mio caso sto costruendo un'app che crea altre app. Non posso presumere che l'utente abbia installato XCode. Sto anche usando MacPorts per creare le librerie da cui dipende la mia app. Devo assicurarmi che questi dylib vengano forniti in bundle con l'app prima di distribuirlo.
Dichiarazione di non responsabilità: non non sono assolutamente qualificato per scrivere questo post, tutto ciò che è contenuto è stato brillato dai documenti di Apple, selezionando le app esistenti e le prove ed errori. Per me funziona, ma molto probabilmente è sbagliato. Per favore mandami un'e-mail se hai correzioni.
La prima cosa che dovresti sapere è che un app bundle è solo una directory.
Esaminiamo la struttura di un ipotetico foo.app.
foo.app/
Contenuti/
Info.plist
Mac OS/
foo
Risorse /
foo.icns
Info.plist è un semplice file XML. Puoi modificarlo con un editor di testo o l'app Property List Editor fornita in bundle con XCode. (Si trova nella directory / Developer / Applications / Utilities /).
Le cose chiave che devi includere sono:
CFBundleName : il nome dell'app.
CFBundleIcon : si presume che un file Icon si trovi nella directory Contents / Resources. Usa l'app Icon Composer per creare l'icona. (Si trova anche nella directory / Developer / Applications / Utilities /) Puoi semplicemente trascinare e rilasciare un png nella sua finestra e dovrebbe generare automaticamente i livelli mip per te.
CFBundleExecutable : nome del file eseguibile che si presume si trovi nella sottocartella Contents / MacOS /.
Ci sono molte più opzioni, quelle sopra elencate sono solo il minimo indispensabile. Ecco della documentazione Apple sul
file Info.plist e sulla
struttura del bundle di app .
Inoltre, ecco un esempio di Info.plist.
<? xml version = "1.0" encoding = "UTF-8"?>
<! DOCTYPE plist PUBLIC "- // Apple Computer // DTD PLIST 1.0 // EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version = "1.0">
<dict>
<key> CFBundleGetInfoString </key>
<string> Foo </string>
<key> CFBundleExecutable </key>
<string> foo </string>
<key> CFBundleIdentifier </key>
<string> com.your-company-name.www </string>
<key> CFBundleName </key>
<string> foo </string>
<key> CFBundleIconFile </key>
<string> foo.icns </string>
<key> CFBundleShortVersionString </key>
<string> 0,01 </string>
<key> CFBundleInfoDictionaryVersion </key>
<string> 6.0 </string>
<key> CFBundlePackageType </key>
<string> APPL </string>
<key> IFMajorVersion </key>
<integer> 0 </integer>
<key> IFMinorVersion </key>
<integer> 1 </integer>
</dict>
</plist>
In un mondo perfetto potresti semplicemente rilasciare il tuo eseguibile in Contents / MacOS / dir ed essere fatto. Tuttavia, se la tua app ha dipendenze dylib non standard, non funzionerà. Come Windows, MacOS viene fornito con il suo tipo speciale di DLL Hell .
Se utilizzi MacPort per creare librerie a cui ti colleghi, le posizioni dei dylibs saranno codificate nel tuo eseguibile. Se esegui l'app su una macchina che ha i dylibs nella stessa identica posizione, funzionerà correttamente. Tuttavia, la maggior parte degli utenti non li installa; quando fanno doppio clic sulla tua app, si bloccherà.
Prima di distribuire il tuo eseguibile, dovrai raccogliere tutti i dylibs che carica e copiarli nel bundle dell'app. Dovrai anche modificare l'eseguibile in modo che cerchi i dylibs nella posizione corretta. cioè dove li hai copiati.
Modificare manualmente un eseguibile sembra pericoloso, giusto? Fortunatamente ci sono strumenti da riga di comando per aiutare.
otool -L nome_eseguibile
Questo comando elencherà tutti i dylibs da cui dipende la tua app. Se ne vedi qualcuno che NON si trova nella cartella System / Library o usr / lib, questi sono quelli che dovrai copiare nel bundle dell'app. Copiali nella cartella / Contents / MacOS /. Successivamente dovrai modificare l'eseguibile per utilizzare i nuovi dylibs.
Innanzitutto, assicurati di eseguire il collegamento utilizzando il flag -headerpad_max_install_names. Questo fa solo in modo che se il nuovo percorso dylib è più lungo del precedente, ci sarà spazio per esso.
In secondo luogo, utilizzare install_name_tool per modificare ogni percorso di dylib.
install_name_tool -change existing_path_to_dylib @ executable_path / blah.dylib executable_name
Come esempio pratico, supponiamo che la tua app utilizzi libSDL e otool elenchi la sua posizione come "/opt/local/lib/libSDL-1.2.0.dylib".
Prima copialo nel bundle dell'app.
cp /opt/local/lib/libSDL-1.2.0.dylib foo.app/Contents/MacOS/
Quindi modifica l'eseguibile per utilizzare la nuova posizione (NOTA: assicurati di averlo creato con il flag -headerpad_max_install_names)
install_name_tool -change /opt/local/lib/libSDL-1.2.0.dylib @ executable_path / libSDL-1.2.0.dylib foo.app/Contents/MacOS/foo
Accidenti, abbiamo quasi finito. Ora c'è un piccolo problema con la directory di lavoro corrente.
Quando avvii la tua app, la directory corrente sarà la directory sopra dove si trova l'applicazione. Ad esempio: se metti foo.app nella cartella / Applcations, la directory corrente quando avvii l'app sarà la cartella / Applicazioni. Non /Applications/foo.app/Contents/MacOS/ come ci si potrebbe aspettare.
Puoi modificare la tua app per tenerne conto, oppure puoi usare questo magico piccolo script di avvio che cambierà la directory corrente e avvierà la tua app.
#! / bin / bash
cd "$ {0% / *}"
./foo
Assicurati di modificare il file Info.plist in modo che CFBundleExecutable punti allo script di avvio e non all'eseguibile precedente.
Ok, tutto fatto adesso. Fortunatamente, una volta che conosci tutte queste cose, le seppellisci in uno script di build.