Kuinka lisätä dynaaminen Swift-kehys komentorivityökaluun

Katsotaanpa kuinka yritin lisätä dynaamisen kehyksen komentorivi-työkaluuni ja keskustella siitä, mikä meni pieleen jokaisessa vaiheessa.

Vaihe 1: lisää se linkitettyihin kehyksiin ja kirjastoihin -osaan

Näin tapahtuu, kun suoritat sovelluksesi:

dyld: Kirjastoa ei ladattu: @ rpath / libswiftAppKit.dylib
Viitteenä: /Users/seanberry/Library/Developer/Xcode/DerivedData/TestCommandLineTool-fnrmhjvjmugvqueaqvbklzwhqvuv/Build/Products/Debug/ThirdParty.framework/Versions/A
Syy: kuvaa ei löydy

ThirdParty.kehys yrittää löytää libswiftAppKit.dylib (joka on osa Swift-vakiokirjastoja) @rpath-hakemistosta.

Voimme nähdä, kuinka ThirdParty.framework määrittelee @rpath suorittamalla

$ oTool -l ThirdParty.framework / Versiot / Nykyinen / ThirdParty
Lataa komento 27
cmd LC_RPATH
cm-koko 48
polku @execvable_path /../ Kehykset (siirto 12)
Lataa komento 28
cmd LC_RPATH
cm-koko 40
polku @ loader_path / kehys (offset 12)

No ammu. Ne eivät ole merkityksellisiä komentorivityökalumme kannalta. Meillä ei ole kansioita nimeltä / Kehykset tai ../Frameworks. Miksi se etsii sieltä Swift-standardikirjastoja?

Koska se on rakennettu iOS- ja Mac-sovelluksille. Tässä on hakemistorakenne Mac-sovelluksen sisällä:

Tämä selittää polun @execvable_path /../ Framework

Ja iOS: n hakemistorakenne sovelluksen sisällä on:

@loader_path on yhtä suuri kuin @execvable_path, kun kehys ladataan suoritettavasta

Ja se selittää polun @ loader_path / Frameworks (offset 12)

Mutta entä me, nöyrä komentorivityökalujen kehittäjä? Swift-standardikirjastot on kytketty staattisesti suoritettavan sisällön sisälle, mutta kolmannen osapuolen kehykset eivät löydä niitä. Valitettavasti niitä ei ole tallennettu vakiopaikkaan jokaisessa Macissa. Kehittäjät voivat käyttää niitä, jotka on haudattu Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx -sovellukseen (mutta äläkä vaadi käyttäjiäsi asentamaan Xcodea).

Joten mitä me teemme? Vakiokäytäntöni, jonka olen nähnyt, on luoda räätälöity kehys projektillesi, tuoda kaikki riippuvuutesi siihen ja kopioida myös nopeat standardikirjastot.

Vaihe 2: Luo mukautettu kehys ja kopioi tavalliset Swift-kirjastot

Tämä kopioi / liittää Swift-standardikirjastot FirstParty.framework / Versiot / Nykyinen / Kehykset /Muista kopioida myös kolmannen osapuolen riippuvuusNyt puitteesi ovat kaikki yhdessä!

Täydellinen! Mennään nyt ja ajaa komentorivityökalumme ...

objc [2335]: Luokka _TtC8Dispatch16DispatchWorkItem on toteutettu molemmissa /Users/seanberry/Library/Developer/Xcode/DerivedData/TestCommandLineTool-fnrmhjvjmugvqueaqvbklzwhqwings/studio/studio/studio/studio/studio/studio/studio/studio/support.jpg ja / Käyttäjät / seanberry / Kirjasto / Kehittäjä / Xcode / DerivedData / TestCommandLineTool-fnrmhjvjmugvqueaqvbklzwhqvuv / Rakenna / Tuotteet / Debug / TestCommandLineTool (0x1005c7698). Toista näistä käytetään. Kumpaa ei ole määritelty.
Toista yllä oleva virhe 20 erilaisella tavalla

Sovelluksesi näkee nyt kaksi erilaista kopiota Swift-vakiokirjastoista: ne, jotka ovat staattisesti linkitetyt suoritettavan sisällön sisällä ja / / Kehykset-kansion sisällä olevat.

Tästä on olemassa kaksi ratkaisua.

Vaihe 3 (vaihtoehto A): Tee sen sijaan Mac-sovellus ja purka suoritettava tiedosto

Tutkin kuuluisia komentorivityökaluja Carthage ja SwiftLint nähdäkseni kuinka he hoitivat tämän ongelman. Osoittautuu, että niitä ei ole asetettu komentorivityökaluiksi! Ne ovat Mac-sovelluksia! Miksi? Koska Mac-sovellus ei linkitä staattisesti vakiokirjastoja. He ottavat itsensä käyttöön komentorivityökaluina lisäämällä ajovaiheen, joka purkaa suoritettavan sovelluspaketista.

#! / Bin / bash
## Poimii Carthage CLI -työkalun sovelluspaketistaan. Tarkoitettu ajaa
# osana Xcode Run Script -kehitysvaihetta.
cp -v "$ {BUILT_PRODUCTS_DIR} / $ {EXECUTABLE_PATH}" "" $ {BUILT_PRODUCTS_DIR} / $ {EXECUTABLE_NAME} "

Voit mennä eteenpäin ja tehdä sen tällä tavalla, ilman ongelmaa. Mutta löysin toisen tavan kiertää tämä asia.

Vaihe 3 (vaihtoehto B): Poista staattinen linkitys käytöstä

Lisää nämä käyttäjän määrittelemiin rakennusasetuksiin:

SWIFT_FORCE_DYNAMIC_LINK_STDLIB KYLLÄ
SWIFT_FORCE_STATIC_LINK_STDLIB EI

Tämä pakottaa suoritettavan linkittämään dynaamisesti kaikki kirjastot. Muista kertoa Xcodelle, mistä ne löytyvät, lisäämällä puitehakemisto Runpath-hakupolkuihin.

@ Executable_path / FirstParty.framework / Versions / Nykyinen / Frameworks

Onnea komentorivityökalullasi!

Sean yrittää saada Xcoden koottavaksi Livefrontilla