Creazione di framework iOS / OSX: è necessario codificarli prima di distribuirli ad altri sviluppatori?


90

Sto imparando a creare framework iOS e OSX. Prendiamo ad esempio iOS, i seguenti passaggi funzionano per me finora:

  1. xcodebuild framework utilizzando -sdk iphonesimulator e l'azione Build
  2. xcodebuild framework usando -sdk iphoneos e l'azione Build
  3. Usa lo strumento lipo per creare un binario universale in modo che lipo -infoproduca:

Le architetture nel file fat: Foo.framework / Foo sono: i386 x86_64 armv7 arm64

Le domande sono:

  1. Ho letto che il mio framework può essere ri-firmato dallo sviluppatore che lo sta usando: "Code Sign on Copy" ma non capisco quali sono i presupposti per esso, ad esempio dovrei aggiungere il passaggio di codesign per codificare quel binario universale con la mia identità di firma prima distribuendolo ad altri sviluppatori?

  2. se il precedente è positivo - devo usare la mia identità "iPhone Distribution: ..." o "iPhone Developer: ..." è sufficiente (in modo che il mio framework che fa parte di qualche progetto iOS superi tutti i tipi di convalida, in particolare la convalida dell'App Store ) ?.

Lo sfondo per la mia risposta è "Errore CodeSign: la firma del codice è richiesta per il tipo di prodotto" Framework "nell'SDK" iOS 8.3 "" che ho visto su una serie di framework di terze parti e Carthage # 235 o "L'oggetto codice non è firmato at all "(un esempio: problema che ho segnalato su Realm # 1998 .

Quindi voglio essere sicuro che gli utenti dei miei framework non incontrino problemi di progettazione del codice quando li usano.

PS Questa domanda diventa ancora più interessante se applicata non a un singolo sviluppatore ma a un'organizzazione che è un fornitore di framework.


Questo commento suggerisce di utilizzare "CODE_SIGN_IDENTITY = iPhone Developer" ma non è chiaro il motivo per cui "Developer" viene utilizzato invece di "iPhone Distribution".
Stanislav Pankevich

Argomento correlato: Esportazione di app con framework incorporato ma senza una risposta definitiva.
Stanislav Pankevich

Ho anche ingannato questa domanda sui forum degli sviluppatori Apple: forums.developer.apple.com/thread/6400 .
Stanislav Pankevich

ho una domanda quando distribuisci il tuo framework, distribuisci una build di debug o una build di rilascio? e se lo distribuisci in build release, come farlo?
niczm25

@ niczm25, questo è un modo per farlo: stanislaw.github.io/2015/11/23/… .
Stanislav Pankevich

Risposte:


137

Ho aperto la taglia: "Alla ricerca di una risposta attingendo a fonti credibili e / o ufficiali". ma da allora non lo ricevo.

Sebbene la risposta fornita da @jackslash sia corretta, racconta solo una parte della storia, quindi voglio scriverne una mia in un modo in cui vorrei averla vista nel momento in cui stavo facendo questa domanda.

L'attualità di questa risposta è: luglio 2015. È molto probabile che le cose cambieranno.

Innanzitutto affermiamo che le azioni necessarie per la corretta firma del codice del framework dovrebbero essere suddivise in passaggi che lo sviluppatore del framework deve eseguire e in passaggi che il consumatore del framework deve eseguire.

TLDR;

Per il framework OSX: lo sviluppatore è libero di distribuire il framework OSX senza codificarlo poiché il consumatore lo ricodificherà comunque.

Per il framework iOS: lo sviluppatore è libero di distribuire il framework iOS senza codificarlo poiché il consumatore lo ricodificherà comunque, ma lo sviluppatore è costretto da Xcode a codificare il proprio framework quando costruisce per il dispositivo iOS.

A causa del radar: "I framework iOS contenenti sezioni del simulatore non possono essere inviati all'App Store" Il consumatore di framework iOS è costretto a eseguire uno script speciale come "copy_frameworks" o "strip_frameworks" che utilizza lipo -removeper rimuovere le sezioni del simulatore dal framework iOS e ri -codesigns ha spogliato il framework perché a questo punto la sua identità di codesigning qualunque fosse (o non fosse) viene rimossa come effetto collaterale della lipo -removemanipolazione.

Segue una risposta più lunga.


Questa risposta non è "attingendo a fonti credibili e / o ufficiali" ma si basa piuttosto su una serie di osservazioni empiriche.

Osservazione empirica n. 1: al consumatore non interessa perché ricodificherà il framework che riceve dallo sviluppatore

Le distribuzioni di framework binari di noti progetti open source su GitHub non sono codificate . Il comando codesign -d -vvvvfornisce: "l'oggetto codice non è firmato affatto" su tutti i framework binari iOS e OSX che ho usato per esplorare. Alcuni esempi: ReactiveCocoa and Mantle , Realm , PromiseKit .

Da questa osservazione è chiaro che gli autori di questi framework intendono che siano codificati dal Consumatore, per loro conto cioè un Consumatore deve utilizzare il flag "Code Sign on Copy" nella fase di compilazione "Embed frameworks" fornita da Xcode o utilizzare una shell personalizzata script che fa la stessa cosa manualmente: codeigns framework per conto del Consumatore.

Non ho trovato alcun singolo esempio del contrario: framework open source che verrebbe distribuito con identità di codeigning, quindi nel resto della risposta presumo che questo approccio ampiamente adottato sia corretto: non è necessario che Framework Developer distribuire il loro framework ad altri sviluppatori con identità di codeigning perché Consumer lo ricodificherà comunque .

Osservazione empirica n. 2 che si applica solo a iOS e che è interamente una preoccupazione dello sviluppatore

Mentre dei consumatori non si preoccupa se quadro che ricevono da sviluppatore è codesigned o no, sviluppatore ha ancora bisogno di codesign loro quadro iOS come parte del suo processo di generazione quando costruiscono per dispositivo iOS perché altrimenti Xcode non costruisce: CodeSign error: code signing is required for product type 'Framework' in SDK 'iOS 8.1'. Per citare Justin Spahr-Summers :

I framework OS X non devono essere codificati al momento della compilazione ... Sfortunatamente, Xcode richiede che i framework iOS siano codificati al momento della compilazione.

Questo risponde abbastanza bene alla mia domanda n. 2: l'identità di "iPhone Developer" è sufficiente per persuadere Xcode in modo che possa costruire il framework iOS per il dispositivo. Questo commento su Cartagine n. 339 dice la stessa cosa.

Osservazione empirica n. 3: strumento lipo

Comportamento specifico di strumento lipo: quando applicato al binario quadro, è sempre rimuove ricorsivamente qualsiasi identità codesign da esso : lipo -create/-remove codesigned framework ... -> not codesigned framework.

Questa potrebbe essere una risposta al motivo per cui tutti gli esempi nell'osservazione n. 1 non sono affatto codificati: la loro identità di siglatura del codice viene spazzata via dopo l'applicazione di lipo, ma poiché secondo l'osservazione n. 1 al consumatore non interessa, va bene.

Questa osservazione è particolarmente rilevante per la prossima osservazione n. 4 su AppStore.

Osservazione empirica n. 4: i framework iOS contenenti sezioni del simulatore non possono essere inviati all'App Store

Questo è ampiamente discusso in: Realm # 1163 e Carthage # 188 e il radar è aperto: rdar: // 19209161 .

Questa è interamente una preoccupazione del consumatore: per il framework universale iOS che il consumatore include nella sua applicazione, quando l'applicazione viene creata, devono eseguire uno script speciale (Custom Run Script Phase) che rimuove la slice del simulatore dal binario di quel framework in modo che l'app possa superare la convalida di AppStore.

Il buon esempio di framework binari che ho trovato in Realm: strip-frameworks.sh .

Viene utilizzato lipoper rimuovere tutte le sezioni di architetture diverse da ${VALID_ARCHS}e quindi ricodificarlo con l'identità del consumatore : è qui che entra in gioco l'osservazione n. 3: il framework deve essere ri-codificato a causa delle manipolazioni lipo su di esso.

Carthage ha lo script CopyFrameworks.swift che fa la stessa cosa a tutti i framework inclusi da Consumer: rimuove le sezioni del simulatore e ricodifica il framework per conto del consumatore.

Inoltre c'è un buon articolo: Rimozione di architetture indesiderate da librerie dinamiche in Xcode .


Ora la panoramica dei passaggi necessari per produrre sia iOS che OSX dal punto di vista dello sviluppatore e del consumatore. Prima quello più facile:

OSX

Sviluppatore:

  1. Costruisce il framework OSX
  2. Lo dà al consumatore

Non sono richieste attività di code design da parte dello sviluppatore.

Consumatore:

  1. Riceve il framework OSX dallo sviluppatore
  2. Copia il framework su Frameworks / directory e lo codifica automaticamente per conto del Consumatore come parte del processo "Code Sign on Copy".

iOS

Sviluppatore:

  1. Crea un framework iOS per il dispositivo. La firma del codice è richiesta da Xcode, l'identità di "iPhone Developer" è sufficiente.
  2. Crea un framework iOS per il simulatore.
  3. Utilizza lipo che produce un framework iOS universale dai due precedenti. A questo punto l'identità di codeigning di 1 passo è persa: il binario del framework universale "non è firmato affatto" ma va bene perché "al consumatore non interessa".
  4. Lo dà al consumatore

Consumatore:

  1. Riceve il framework iOS dallo sviluppatore
  2. Copia il framework nella directory Frameworks / (questo passaggio potrebbe essere ridondante a seconda dello script nel passaggio 3).
  3. Utilizza uno script speciale come parte del processo di compilazione: questo script elimina il simulatore dal framework iOS e quindi lo ricodifica per conto del consumatore.

9
Questa è una preziosa recensione. Bello
jackslash il

@Stanislaw grazie per gli approfondimenti e i preziosi dati. Mentre sto scrivendo un framework progettato da me per gli sviluppatori, voglio che siano in grado di prendere il framework così com'è e usarlo senza la necessità di creare uno script speciale per caricarlo nell'app store. Penso che GoogleMobileAd funzioni in questo modo. ma dici che devono eseguire determinati script? hai idea di come GoogleMobileAds non lo richieda? grazie
Michael A

@MichaelA, in effetti è interessante. Guarderò.
Stanislav Pankevich

Puoi darmi un link agli annunci GoogleMobile che stai utilizzando?
Stanislav Pankevich

1
Grazie per avermi risparmiato tempo, ha funzionato per me. Xcode 7.3, Mac OS X 10.11.4.
eugen

21

Dalla lettura del thread collegato sul repo di Carthage sembra relativamente semplice. Se stai distribuendo il framework binario devi firmarlo in codice e se stai distribuendo il sorgente tramite carthage o cialde di cacao non lo fai poiché questi strumenti si occupano di questo con metodi diversi.

Il motivo per cui è necessario firmarlo in codice quando si distribuisce il framework binario è che Xcode non produrrà un binario framework senza che il codice lo firmi. Se si tenta di non firmare il codice del framework binario, viene visualizzato questo errore:

CodeSign error: code signing is required for product type 'Framework' in SDK 'iOS 8.1'

Non importa con quale identità si firma il codice del framework (iPhone Developer o iPhone Distribution) perché, come si fa notare, il framework verrà ri-codificato con l'impostazione "code sign on copy". Ciò significa che il tuo framework verrà ricodificato dal certificato appropriato dal profilo dello sviluppatore del consumatore del framework quando il tuo framework verrà copiato nella loro applicazione. Ciò significa che non ci saranno problemi con l'App Store in quanto vedrà solo la firma del codice finale dal consumatore del framework.

Alla fine della giornata, potresti anche firmare il codice del tuo file binario .framework perché non vuoi dover mantenere un processo di compilazione esotico e poiché Xcode produrrà solo framework firmati, non dovresti allontanarti troppo dal impostazioni predefinite. Non importa comunque perché il consumatore finale lo firmerà nuovamente.


nella tua risposta, nel secondo paragrafo, stai dicendo che non è necessario codificare il framework perché sarà ricodificato dal consumatore e sono anche sicuro al 95% che sia vero, ma non capisco perché allo stesso tempo nel primo paragrafo stai dicendo: "Se stai distribuendo il framework binario devi firmarlo in codice" - qual è la differenza - se distribuisco framework binario (cioè non la sua fonte tramite carthage o cocoapods) perché Avrei bisogno di codificarlo?
Stanislav Pankevich

Penso che non dovrei codificare il mio framework qualunque tipo di distribuzione che utilizzo (file .framework zippato o carthage o cocoapods). Esempi: tutte le seguenti distribuzioni di framework binari non sono codificate: Realm , ReactiveCocoa , OCMockito .
Stanislav Pankevich

Quindi sono un po 'confuso con il tuo "Se stai distribuendo il framework binario devi firmarlo in codice", che (imho) contraddice il resto della tua risposta. Si prega di precisare. Inoltre, tieni presente che ho aperto questa taglia come "Alla ricerca di una risposta attingendo a fonti credibili e / o ufficiali".
Stanislav Pankevich

1
Sì, ho anche esaminato Realm e OCMockito. Realm ha identità "iPhone Developer" e sì, OCMockito è una libreria statica. Penso di aver capito il problema: è lipo che rimuove la firma del codice da iphoneos quando combina iphoneos codificati e iphonesimulator non codificati.
Stanislav Pankevich

1
ho una domanda quando distribuisci il tuo framework, distribuisci una build di debug o una build di rilascio? e se lo distribuisci in build release, come farlo?
niczm25

1

La risposta di Stanislav Pankevich sopra è molto valida e corretta. Ma tieni presente che a partire da Xcode 9.4, l'IDE ti chiederà di disabilitare la firma del codice per iOS Cocoa Touch Frameworks. Apple qui ora dice che non è consigliabile firmare con il codice il tuo .framework.

Spero che questo possa essere d'aiuto.


1
Hai una fonte per Apple che consiglia di non firmare framework?
Rick,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.