2012-09-27 12 views
6

Sto cercando di trovare il modo migliore per impacchettare una libreria statica (chiamiamola Lib1) che include una classe opzionale (ad esempio, ClassA), che a sua volta richiede una seconda libreria statica (Lib2). In altre parole, Lib2 è necessario solo se si fa riferimento a ClassA nel codice del progetto. Le cose sembrano funzionare bene, a meno che Lib1 non venga usato in un progetto che non usa ClassA (e quindi non include Lib2), ma richiede il flag link -ObjC (a causa di altre dipendenze del progetto, non mie).ObjC: Come compilare una libreria statica che include classi opzionali che dipendono da una libreria di terze parti

sto cercando di trovare una una soluzione facile per i seguenti tre scenari:
1) progetto prevede la mia lib statica, non usa la classe facoltativa, non specifica il flag -ObjC
2) progetto include la mia lib statica, NON usa la classe opzionale, ma richiede -ObjC flag
3) progetto include la mia libreria statica statica + seconda lib, e DOES usa la classe opzionale (non ci interessa il flag -ObjC a questo punto)

C'è un flag linker là fuori per rimuovere la mia classe opzionale dall'app finale del progetto in modo che non richieda la seconda lib statica? Immagino che le mie altre alternative siano di rilasciare più versioni della mia lib statica, una che include la classe di opzioni (la scelta standard), una che non lo fa (l'alternativa, per i progetti con requisiti ObjC), o magari fornire un file stub, che fornisce implementazioni vuote di tutte le classi necessarie dalla seconda libreria statica? Sembra che potrebbe essere un problema comune nel mondo delle librerie statiche ... esiste una best practice per questo scenario?

Grazie!


Soluzione:

1) suggerire ai miei utenti -ObjC che usano -force_load invece. (grazie Rob!)
2) Per gli utenti che non possono fare 1, avrò una build alternativa che non include ClassA

risposta

6

La pratica migliore è sempre quella di avere il collegamento binario finale di tutte le librerie statiche richieste . Non si dovrebbe mai raggruppare una libreria statica in un'altra. Non dovresti assolutamente mai raggruppare una libreria statica ben conosciuta (cioè open source) in una libreria statica che spedisci. Questo può creare incredibili mal di testa per il consumatore finale perché possono finire con più versioni dello stesso codice. Rintracciare i bug che possono venire da questo è follemente difficile. Se sono fortunati, avranno solo errori di compilazione confusi. Se sono sfortunati, il loro codice si comporterà in modi imprevedibili e arresti anomali casuali.

Spedire tutte le librerie statiche separatamente. Dì ai tuoi clienti quali hanno bisogno di collegare per varie configurazioni. Cercare di evitare ciò rende le loro vite difficili.

Alcune altre discussioni che possono essere utili:


Il flag -ObjC dovrebbe impedire la rimozione automatica di ClassA interamente, se usato o meno (vedere TN1490 per ulteriori dettagli).

Se ClassA non viene mai utilizzato, tranne in alcune circostanze e si desidera risparmiare spazio, è consigliabile spostare ClassA nella propria libreria statica. O utilizzare #ifdef per compilarlo condizionatamente.

In alternativa, è possibile rimuovere il flag e utilizzare -force_load per caricare individualmente tutte le unità di compilazione di sola categoria (che è il problema -ObjC utilizzato per indirizzare).

+0

Grazie per i collegamenti, mi hanno aiutato a comprendere più a fondo il trucco di una libreria statica! –

+0

In realtà non sto raggruppando librerie statiche nella mia libreria statica. Nella mia lib statica (chiamiamola Lib1), ho una classe (ad esempio ClassA) che dipende da un'altra lib (Lib2) statica collegata all'app. ClassA non sarà mai usato senza Lib2 incluso. Sembra che il compilatore/linker sia abbastanza intelligente da escludere ClassA dall'app finale, se non è stata utilizzata. Tuttavia, se viene specificato il flag -ObjC linker, il compilatore/linker tenta di risolvere le dipendenze Lib2 di ClassA, ma non può ... indipendentemente dal fatto che ClassA abbia mai fatto riferimento nell'app. Speravo in una bandiera magica del linker che avrebbe tolto ClassA –

+1

Aggiornato con alcune considerazioni. Non è facile risolvere questo problema. ObjC è altamente dinamico, ed è del tutto normale fare riferimento a classi al runtime in modi che il linker non può vedere al momento del collegamento (il caricamento del pennino è fatto in questo modo). È molto difficile che il linker funzioni correttamente se si inserisce tutto nello stesso file senza passare i parametri -force_load individuali anziché il parametro big -ObjC. –

Problemi correlati