Skip to content

Commit 6c24bf8

Browse files
committed
Clarify the framework conversion section
Also, switch to embedding the Swift standard libraries in the app's Frameworks directory. It works just as well (@executable_path/../Frameworks is one of the framework's rpaths) and is consistent with typical Swift apps.
1 parent ab21aca commit 6c24bf8

File tree

4 files changed

+42
-16
lines changed

4 files changed

+42
-16
lines changed

README.md

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -201,22 +201,56 @@ Text marked as `{}` will vary.
201201

202202
## Converting the Swift App to a Framework
203203

204-
Create a new Cocoa Framework target in the Xcode project
205-
named SwiftAppLibrary, then change the Target Membership of
206-
`AppDelegate.swift` and `MainMenu.xib` to only SwiftAppLibrary
207-
in Xcode's File Inspector in the right sidebar:
204+
Create a new Cocoa Framework target in the Xcode project,
205+
206+
![Select the Cocoa Framework template](tutorial/xcode-cocoa-framework-template-icon.png)
207+
208+
with Swift as the default language.
209+
210+
![Select Swift as the default language](tutorial/xcode-create-project-language-swift.png)
211+
212+
Name the framework SwiftAppLibrary.
213+
214+
### Framework Configuration
215+
216+
To move over our application code and UI, change the Target
217+
Membership of `AppDelegate.swift` and `MainMenu.xib` in Xcode's
218+
File Inspector in the right sidebar so that they are only
219+
included in SwiftAppLibrary:
208220

209221
![Target Membership](tutorial/xcode-target-membership.png)
210222

211-
In the new framework's build settings, set **Always Embed Swift
212-
Standard Libraries** to **Yes**.
223+
Xcode will place the built framework in a temporary directory
224+
(`~/Library/Developer/Xcode/DerivedData/`) with an unpredictable
225+
subpath. So that Cabal will be able to find the framework for
226+
linking, add a new **Run Script** build phase to create a
227+
symlink to the built framework in `build/`:
228+
229+
```sh
230+
set -u
231+
ln -sf "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}" "${PROJECT_DIR}/build/"
232+
```
233+
234+
### App Bundle Configuration
213235

214236
Drag the `SwiftHaskell` executable we built previously with
215237
Stack into Xcode from the `build/` directory that we symlinked
216238
it into, but do not add it to any targets when prompted:
217239

218240
![The SwiftHaskell executable in Xcode](tutorial/xcode-files-swifthaskell-executable.png)
219241

242+
When Xcode creates Swift frameworks, it expects that the
243+
application that links the framework will include the Swift
244+
standard libraries. Xcode automatically adds these libraries to
245+
Swift applications. Since our application executable is built
246+
with Haskell and not Swift, we'll need to explicitly tell Xcode
247+
to include the Swift standard libraries in our application.
248+
249+
In the app target's Build Settings tab, set **Always Embed Swift
250+
Standard Libraries** to **Yes**:
251+
252+
![Always Embed Swift Standard Libraries: Yes](tutorial/xcode-embed-swift-standard-libs.png)
253+
220254
In the SwiftHaskell app target's Build Phases, remove the
221255
**Compile Sources** and **Link Binary With Libraries**
222256
phases, and add a new **Copy Files** phase that copies the
@@ -227,14 +261,6 @@ directory:
227261

228262
![Copy into Executables](tutorial/xcode-copy-files-swifthaskell-executable.png)
229263

230-
Finally, in the SwiftAppLibrary framework target's Build Phases,
231-
add a new **Run Script** phase to create a symlink to the built
232-
framework for us to link to from Cabal:
233-
234-
```sh
235-
set -u
236-
ln -sf "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}" "${PROJECT_DIR}/build/"
237-
```
238264

239265
Build the SwiftAppLibrary framework in Xcode to prepare for the
240266
next sections.

SwiftHaskell.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,6 @@
395395
BFABC4641E4C1DD1006036C6 /* Debug */ = {
396396
isa = XCBuildConfiguration;
397397
buildSettings = {
398-
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
399398
CODE_SIGN_IDENTITY = "";
400399
COMBINE_HIDPI_IMAGES = YES;
401400
DEFINES_MODULE = YES;
@@ -423,7 +422,6 @@
423422
BFABC4651E4C1DD1006036C6 /* Release */ = {
424423
isa = XCBuildConfiguration;
425424
buildSettings = {
426-
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
427425
CODE_SIGN_IDENTITY = "";
428426
COMBINE_HIDPI_IMAGES = YES;
429427
DEFINES_MODULE = YES;
@@ -450,6 +448,7 @@
450448
BFABC4E61E4D781D006036C6 /* Debug */ = {
451449
isa = XCBuildConfiguration;
452450
buildSettings = {
451+
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
453452
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
454453
COMBINE_HIDPI_IMAGES = YES;
455454
INFOPLIST_FILE = SwiftHaskell/Info.plist;
@@ -462,6 +461,7 @@
462461
BFABC4E71E4D781D006036C6 /* Release */ = {
463462
isa = XCBuildConfiguration;
464463
buildSettings = {
464+
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
465465
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
466466
COMBINE_HIDPI_IMAGES = YES;
467467
INFOPLIST_FILE = SwiftHaskell/Info.plist;
4.78 KB
Loading
12.2 KB
Loading

0 commit comments

Comments
 (0)