Kako dodati dinamički okvir Swift u Alat naredbenog retka

Provjerimo kako sam pokušao dodati dinamički okvir svom Alatu naredbenog retka i razgovarati o tome što je pošlo po zlu svakom koraku.

1. korak: dodajte ga u odjeljak "Povezani okviri i knjižnice"

To se događa kada pokrenete aplikaciju:

dyld: Biblioteka nije učitana: @ rpath / libswiftAppKit.dylib
Navedeno iz: /Users/seanberry/Library/Developer/Xcode/DerivedData/TestCommandLineTool-fnrmhjvjmugvqueaqvbklzwhqvuv/Build/Products/Debug/ThirdParty.framework/Versions/VersionsAA
Razlog: slika nije pronađena

ThirdParty.framework pokušava pronaći libswiftAppKit.dylib (koji je dio Swift standardnih knjižnica) u direktoriju @rpath.

Vidimo kako ThirdParty.framework definira @rpath trčanjem

$ oTool -l ThirdParty.framework / Verzije / Trenutni / ThirdParty
Naredba za učitavanje 27
cmd LC_RPATH
cmdsize 48
put @executable_path /../ okviri (pomak 12)
Naredba za učitavanje 28
cmd LC_RPATH
cmdsize 40
staza @ loader_path / Frameworks (pomak 12)

Pa pucaj. One nisu relevantne za naš alat Alat naredbenog retka. Nemamo mape pod nazivom / Frameworks ili ../Frameworks. Zašto se traže tamo standardne knjižnice Swift?

Jer je stvoren za iOS i Mac aplikacije. Evo strukture direktorija unutar Mac aplikacije:

To objašnjava okvire putanje @executable_path /../

A za iOS je struktura direktorija unutar aplikacije sljedeća:

@loader_path jednak je @executable_path kad se okvir učita iz izvršne datoteke

To objašnjava put @ loader_path / Frameworks (pomak 12)

Ali što je s nama, skromnim programerom alata za naredbene crte? Standardne knjižnice Swift statički su povezane u našoj izvršnoj datoteci, ali ih treći okviri ne mogu pronaći. Nažalost, nisu pohranjeni na standardno mjesto na svim Mac računalima. Programeri mogu pristupiti njima sahranjenim unutar Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx (ali molim vas, ne zahtijevaju od vaših korisnika da instaliraju Xcode).

Pa što da radimo? Standardna praksa koju sam vidio jest stvoriti prilagođeni okvir za svoj projekt, uvesti sve svoje zavisnosti u njega, a zatim kopirati i brze standardne knjižnice.

Korak 2: Stvorite prilagođeni okvir i kopirajte standardne Swift knjižnice

Ovo će kopirati / zalijepiti Swift standardne biblioteke unutar FirstParty.framework / Verzije / Trenutni / okviri /Obavezno kopirajte i u svoju treću stranuSada su vaši okviri svi zajedno!

Savršen! Ajmo sada i pokrenimo naš alat za naredbenu liniju ...

objc [2335]: Klasa _TtC8Dispatch16DispatchWorkItem implementirana je u oba /Users/seanberry/Library/Developer/Xcode/DerivedData/TestCommandLineTool-fnrmhjvjmugvqueaqvbklzwhqvuv/fybmwytmFefDrfrrrrrrrrrrrrrrrrrr / i / Korisnici / seanberry / Library / Developer / Xcode / DerivedData / TestCommandLineTool-fnrmhjvjmugvqueaqvbklzwhqvuv / Build / Products / Debug / TestCommandLineTool (0x1005c7698). Jedna od dvije bit će korištena. Koji je nedefiniran.
PONOVNO POPRAVITE POGREŠU NA 20 RAZLIČITIH PUTA

Vaša aplikacija sada vidi dvije različite kopije standardne knjižnice Swift: onu koja je statički povezana unutar izvršne datoteke i onu u mapi / Frameworks.

Odavde postoje dva rješenja.

Korak 3 (opcija A): Umjesto toga napravite aplikaciju za Mac i izdvojite izvršnu datoteku

Ispitao sam poznate alate naredbenog retka Carthage i SwiftLint da vidim kako rješavaju ovaj problem. Ispada da nisu postavljeni kao alati naredbenog retka! Oni su Mac aplikacije! Zašto? Budući da aplikacija Mac ne povezuje statički standardne knjižnice. Oni se raspoređuju kao alati naredbenog retka dodavanjem faze pokretanja koja izdvaja izvršnu datoteku iz paketa aplikacija.

#! / Bin / bash
## Ekstrahira CLI alat za dostavu iz paketa aplikacije. Treba biti pokrenut
# kao dio faze izgradnje Xcode Run Script.
cp -v "$ {BUILT_PRODUCTS_DIR} / $ {EXECUTABLE_PATH}" "$ {BUILT_PRODUCTS_DIR} / $ {EXECUTABLE_NAME}"

Možete nastaviti naprijed i to tako, nema problema. Ali našao sam drugi način oko ovog pitanja.

Korak 3 (opcija B): Onemogućite statičko povezivanje

Dodajte ih u svoje korisničke postavke gradnje:

SWIFT_FORCE_DYNAMIC_LINK_STDLIB DA
SWIFT_FORCE_STATIC_LINK_STDLIB NE

To će natjerati vašu izvršnu datoteku da dinamički poveže sve knjižnice. Obavezno kažite Xcode-u gdje ih pronaći dodavanjem okvirne mape u 'Putove pretraživanja "

@ executable_path / FirstParty.framework / inačice / Tekući / okviri

Sretno s vašim alatom naredbenog retka!

Sean pokušava dobiti Xcode za sastavljanje na Livefrontu