Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d0791226a | ||
|
|
f4e9fe6d04 | ||
|
|
23e63b31b6 | ||
|
|
5ccabf268b | ||
|
|
52703c2dc9 | ||
|
|
b545a3ae24 | ||
|
|
8f52ca7cb9 | ||
|
|
624b296fa4 | ||
|
|
b4e8e344e1 | ||
|
|
6e2df7fc73 | ||
|
|
4a6f94a435 | ||
|
|
7f46097382 | ||
|
|
6c24bf8649 | ||
|
|
ab21acac78 | ||
|
|
4e47c437f3 | ||
|
|
163d0d0a6d | ||
|
|
3c0871874d | ||
|
|
fcf526afb1 | ||
|
|
31d3a4771b | ||
|
|
7e9f47e85a | ||
|
|
4f82e89ba9 | ||
|
|
e504bbd81d | ||
|
|
01fd35818c |
@@ -1,14 +1,42 @@
|
||||
# Integrating Haskell with Swift Mac Apps
|
||||
|
||||
In this tutorial, we'll create a Mac app using Swift and Xcode
|
||||
to build the UI, and Haskell to implement backend logic.
|
||||
|
||||
A basic familiarity with Haskell, Swift, Objective-C, C, Xcode,
|
||||
and shell scripting will be assumed.
|
||||
|
||||
### Table of Contents
|
||||
|
||||
1. [Project Setup](#project-setup)
|
||||
2. [Exporting Haskell Functions](#exporting-haskell-functions)
|
||||
3. [Importing Haskell's Generated FFI Headers into Swift](#importing-haskells-generated-ffi-headers-into-swift)
|
||||
4. [Converting the Swift App to a Framework](#converting-the-swift-app-to-a-framework)
|
||||
1. [Framework Configuration](#framework-configuration)
|
||||
2. [App Bundle Configuration](#app-bundle-configuration)
|
||||
5. [Linking to the Framework](#linking-to-the-framework)
|
||||
6. [Starting Cocoa](#starting-cocoa)
|
||||
7. [Linking to the Executable](#linking-to-the-executable)
|
||||
8. [Calling Haskell from Swift](#calling-haskell-from-swift)
|
||||
9. [Passing Complex Data Types](#passing-complex-data-types)
|
||||
1. [Bytes](#bytes)
|
||||
2. [Functions and Closures](#functions-and-closures)
|
||||
10. [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Project Setup
|
||||
|
||||
To start, create a new Cocoa Application Xcode project
|
||||
with Swift as the default language:
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
with Swift as the default language.
|
||||
|
||||
Then `cd` into the directory with the `.xcodeproj` and create a
|
||||
new stack project:
|
||||

|
||||
|
||||
Name the project SwiftHaskell.
|
||||
|
||||
`cd` into the directory with the `.xcodeproj` and create a new
|
||||
stack project:
|
||||
|
||||
```sh
|
||||
$ cd SwiftHaskell
|
||||
@@ -136,7 +164,9 @@ create a symlink to the built executable's location for later.
|
||||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
|
||||
# Change EXECUTABLE_NAME to the name of your Haskell executable.
|
||||
EXECUTABLE_NAME=SwiftHaskell
|
||||
|
||||
DIST_DIR="$(stack path --dist-dir)"
|
||||
GHC_VERSION="$(stack exec -- ghc --numeric-version)"
|
||||
GHC_LIB_DIR="$(stack path --compiler-bin)/../lib/ghc-$GHC_VERSION"
|
||||
@@ -159,53 +189,116 @@ module_map="${module_map} export *${NL}"
|
||||
module_map="${module_map}}"
|
||||
echo "${module_map}" > "${STUB_MODULE_MAP}"
|
||||
|
||||
# Symlink to the current GHC's header directory from a more
|
||||
# convenient place for Xcode to find.
|
||||
# Symlink to the current GHC's header directory so we can add it
|
||||
# to Xcode's include path as $(PROJECT_DIR)/build/ghc/include.
|
||||
mkdir -p build/ghc
|
||||
ln -sf "${GHC_LIB_DIR}/include" build/ghc/
|
||||
|
||||
# Symlink to the Haskell executable for Xcode.
|
||||
# Symlink to the Haskell executable so we can easily drag it
|
||||
# into Xcode to use as the executable for the app bundle.
|
||||
ln -sf "../${DIST_DIR}/build/${EXECUTABLE_NAME}/${EXECUTABLE_NAME}" build/
|
||||
```
|
||||
|
||||
Change the value of the `EXECUTABLE_NAME` variable to the
|
||||
name of the executable in your `.cabal` file if you named it
|
||||
something other than SwiftHaskell.
|
||||
|
||||
Save the script as `link-deps.sh`, run `stack build`, and then
|
||||
run `bash link-deps.sh` to prepare for the next section.
|
||||
|
||||
Running the script will create
|
||||
`SwiftHaskell/include/module.modulemap` and two symlinks in
|
||||
the project's `build/` directory:
|
||||
|
||||
- `SwiftHaskell` `-> ../.stack-work/dist/{arch}/Cabal-{version}/build/SwiftHaskell/SwiftHaskell`
|
||||
- `ghc`
|
||||
- `include` `-> ~/.stack/programs/{arch}/ghc-{version}/bin/../lib/ghc-{version}/include`
|
||||
|
||||
Text marked as `{}` will vary.
|
||||
|
||||
## Converting the Swift App to a Framework
|
||||
|
||||
Create a new Cocoa Framework target in the Xcode project
|
||||
named SwiftAppLibrary, then change the Target Membership of
|
||||
`AppDelegate.swift` and `MainMenu.xib` to only SwiftAppLibrary
|
||||
in Xcode's File Inspector in the right sidebar:
|
||||
Create a new Cocoa Framework target in the Xcode project,
|
||||
|
||||

|
||||
|
||||
with Swift as the default language.
|
||||
|
||||

|
||||
|
||||
Name the framework SwiftAppLibrary.
|
||||
|
||||
### Framework Configuration
|
||||
|
||||
To move over our application code and UI, change the Target
|
||||
Membership of `AppDelegate.swift` and `MainMenu.xib` in Xcode's
|
||||
File Inspector in the right sidebar so that they are only
|
||||
included in SwiftAppLibrary:
|
||||
|
||||

|
||||
|
||||
In the new framework's build settings, set **Always Embed Swift
|
||||
Standard Libraries** to **Yes**.
|
||||
In `AppDelegate.swift`, remove the `@NSApplicationMain`
|
||||
attribute from the `AppDelegate` class, as we don't want an
|
||||
auto-generated `main` function in our framework. We will
|
||||
implement an equivalent way to start Cocoa later, to be called
|
||||
from the Haskell executable's `main`.
|
||||
|
||||
Drag the `SwiftHaskell` executable we built previously with
|
||||
Stack into Xcode from the `build/` directory that we symlinked
|
||||
it into, but do not add it to any targets when prompted:
|
||||
Xcode will place the built framework in a temporary directory
|
||||
(`~/Library/Developer/Xcode/DerivedData/`) with an unpredictable
|
||||
subpath. So that Cabal will be able to find the framework for
|
||||
linking, add a new **Run Script** build phase
|
||||
|
||||

|
||||

|
||||
|
||||
In the SwiftHaskell app target's Build Phases, remove the
|
||||
**Compile Sources** and **Link Binary With Libraries**
|
||||
phases, and add a new **Copy Files** phase that copies the
|
||||
`SwiftHaskell` executable into the app bundle's Executables
|
||||
directory:
|
||||
|
||||

|
||||
|
||||
Finally, in the SwiftAppLibrary framework target's Build Phases,
|
||||
add a new **Run Script** phase to create a symlink to the built
|
||||
framework for us to link to from Cabal:
|
||||
that creates a symlink to the built framework in `build/`:
|
||||
|
||||
```sh
|
||||
set -u
|
||||
ln -sf "${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}" "${PROJECT_DIR}/build/"
|
||||
```
|
||||
|
||||
### App Bundle Configuration
|
||||
|
||||
Drag the `SwiftHaskell` executable we built previously with
|
||||
Stack into Xcode from the `build/` directory that we symlinked
|
||||
it into,
|
||||
|
||||

|
||||
|
||||
but do not add it to any targets when prompted:
|
||||
|
||||

|
||||
|
||||
When Xcode creates Swift frameworks, it expects that the
|
||||
application that links the framework will include the Swift
|
||||
standard libraries. Xcode automatically adds these libraries to
|
||||
Swift applications. Since our application executable is built
|
||||
with Haskell and not Swift, we'll need to explicitly tell Xcode
|
||||
to include the Swift standard libraries in our application.
|
||||
|
||||
In the app target's Build Settings tab, set **Always Embed Swift
|
||||
Standard Libraries** to **Yes**:
|
||||
|
||||

|
||||
|
||||
In the app target's Build Phases, remove the **Compile Sources**
|
||||
and **Link Binary With Libraries** phases. We are using Stack to
|
||||
build the app's executable instead of Xcode.
|
||||
|
||||
Add a new **Copy Files** phase that copies the `SwiftHaskell`
|
||||
executable into the app bundle's Executables directory:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

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

|
||||
|
||||
## Linking to the Framework
|
||||
|
||||
Add these options to the executable's section in the `.cabal`
|
||||
@@ -226,35 +319,48 @@ executable SwiftHaskell
|
||||
executable where the dynamic linker should look for shared
|
||||
libraries.
|
||||
|
||||
## Starting the GUI
|
||||
See [the Flag Reference in the GHC Users'
|
||||
Guide][ghc-guide-flags] and [`man 1 ld`][man-ld] for more details.
|
||||
|
||||
[ghc-guide-flags]: https://downloads.haskell.org/~ghc/8.0.2/docs/html/users_guide/flags.html
|
||||
[man-ld]: x-man-page://1/ld
|
||||
|
||||
## Starting Cocoa
|
||||
|
||||
Because Haskell has control over the program's entry point
|
||||
(`main`), we'll need to have it call out to Swift to
|
||||
start Cocoa's main thread. Add this top level function to
|
||||
`AppDelegate.swift`:
|
||||
|
||||
```swift
|
||||
@_cdecl("runNSApplication")
|
||||
func runNSApplication() {
|
||||
let app = NSApplication.shared()
|
||||
var topObjects: NSArray = []
|
||||
NSNib.init(nibNamed: "MainMenu", bundle: Bundle(for: AppDelegate.self))!
|
||||
.instantiate(withOwner: app, topLevelObjects: &topObjects)
|
||||
app.run()
|
||||
}
|
||||
```
|
||||
|
||||
`@_cdecl` sets the symbol name of the Swift function, overriding
|
||||
normal symbol mangling.
|
||||
|
||||
In `SwiftAppLibrary.h`, add a `FOUNDATION_EXPORT` C prototype
|
||||
for the function, so that its symbol gets marked as public and
|
||||
is exported from the framework:
|
||||
(`main`), we'll need to have it call out to Cocoa to start its
|
||||
main thread. In `SwiftAppLibrary.h`, declare a new function
|
||||
named `runNSApplication` and mark it as `FOUNDATION_EXPORT` to
|
||||
indicate that it should be exported from the framework:
|
||||
|
||||
```c
|
||||
FOUNDATION_EXPORT void runNSApplication(void);
|
||||
```
|
||||
|
||||
Implement the function by adding a new Objective-C `.m` file to
|
||||
the framework target containing
|
||||
|
||||
```objective-c
|
||||
#import "SwiftAppLibrary.h"
|
||||
|
||||
@interface AClassInThisFramework : NSObject @end
|
||||
@implementation AClassInThisFramework @end
|
||||
|
||||
void runNSApplication(void) {
|
||||
NSApplication *app = [NSApplication sharedApplication];
|
||||
NSBundle *bundle = [NSBundle bundleForClass:[AClassInThisFramework class]];
|
||||
NSArray *topObjects;
|
||||
[[[NSNib alloc] initWithNibNamed:@"MainMenu" bundle:bundle]
|
||||
instantiateWithOwner:app topLevelObjects:&topObjects];
|
||||
[app run];
|
||||
}
|
||||
```
|
||||
|
||||
This *is* possible to write in Swift, however as of Swift 3.0.2,
|
||||
the annotation to export unmangled C symbols (`@_cdecl`) is not
|
||||
documented as stable. Additionally, whole module optimization
|
||||
will assume that `@_cdecl` symbols are unused and remove them.
|
||||
|
||||
In `Main.hs`, import the foreign function and call it from
|
||||
the end of `main`:
|
||||
|
||||
@@ -280,21 +386,24 @@ main = do
|
||||
main run loop. Use `Control.Concurrent.forkIO` before calling
|
||||
`runNSApplication` to run other tasks as needed.
|
||||
|
||||
Run `stack build`, and build and run the `SwiftHaskell` app
|
||||
target in Xcode to launch the app and see the default window
|
||||
from `MainMenu.xib`:
|
||||
Build the `SwiftHaskellLibrary` framework in Xcode, then `stack
|
||||
build`, and then finally build and run the `SwiftHaskell`
|
||||
app target to launch the app and see the default window from
|
||||
`MainMenu.xib`:
|
||||
|
||||

|
||||
|
||||
## Completing Linking Setup
|
||||
## Linking to the Executable
|
||||
|
||||
Add `$(PROJECT_DIR)/SwiftHaskell/include` to the framework
|
||||
target's **Swift Compiler - Search Paths, Import Paths** setting
|
||||
in Xcode,
|
||||
To tell Xcode where to find our `module.modulemap`, add
|
||||
`$(PROJECT_DIR)/SwiftHaskell/include` to the framework target's
|
||||
**Swift Compiler - Search Paths, Import Paths** setting in
|
||||
Xcode,
|
||||
|
||||

|
||||
|
||||
and `$(PROJECT_DIR)/build/ghc/include` to the framework's **User
|
||||
and, for the GHC headers the module depends on, add
|
||||
`$(PROJECT_DIR)/build/ghc/include` to the framework's **User
|
||||
Header Search Paths** setting:
|
||||
|
||||

|
||||
@@ -303,14 +412,14 @@ In order for the framework to be able to link to symbols in the
|
||||
Haskell executable, we need to tell the linker to leave symbols
|
||||
undefined and have them be resolved at runtime.
|
||||
|
||||
Add `-undefined dynamic_lookup` to the framework's **Other
|
||||
Linker Flags** setting.
|
||||
Add [`-undefined dynamic_lookup`][man-ld] to the framework's
|
||||
**Other Linker Flags** setting.
|
||||
|
||||
Be aware that this means that link errors will occur at runtime
|
||||
instead of at link time. Also note that the framework linking
|
||||
to symbols in the executable (and depending on the generated
|
||||
headers), and the executable linking to the framework, creates
|
||||
a circular dependency. When initially building the project, you
|
||||
a circular dependency. When building the project clean, you
|
||||
will need to build the components in this order:
|
||||
|
||||
- `stack build` to generate the Haskell FFI export headers.
|
||||
@@ -335,6 +444,7 @@ Add the Haskell sources as input files:
|
||||
```
|
||||
$(PROJECT_DIR)/src/Main.hs
|
||||
$(PROJECT_DIR)/SwiftHaskellLibrary.cabal
|
||||
$(PROJECT_DIR)/stack.yaml
|
||||
```
|
||||
|
||||
And the executable as an output file:
|
||||
@@ -361,23 +471,39 @@ main = defaultMainWithHooks $ simpleUserHooks
|
||||
## Calling Haskell from Swift
|
||||
|
||||
We're now ready to use exported Haskell functions from Swift.
|
||||
Import `SwiftHaskell` at the top of `AppDelegate.swift`
|
||||
Import the module we defined in our `module.modulemap`,
|
||||
`SwiftHaskell`, at the top of `AppDelegate.swift`:
|
||||
|
||||
```swift
|
||||
import SwiftHaskell
|
||||
```
|
||||
|
||||
Add a new label to the window in `MainMenu.xib` for us to write
|
||||
the result of our Haskell function `square` into, and add it as
|
||||
an `@IBOutlet` to the `AppDelegate`:
|
||||
Let's add a new label to the window for us to write the result
|
||||
of our Haskell function `square` into. Open `MainMenu.xib` and
|
||||
select the window object in the left sidebar to bring it into
|
||||
view. Then drag in a label from the object library in the right
|
||||
sidebar into the window:
|
||||
|
||||

|
||||
|
||||
Now option-click on `AppDelegate.swift` in the file list to open
|
||||
it in an assistant editor. Holding the control key, drag the
|
||||
label from the window into the `AppDelegate` class to add and
|
||||
connect a new `@IBOutlet`:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Adding the outlet will add a new property to the `AppDelegate`:
|
||||
|
||||
```swift
|
||||
@IBOutlet weak var label: NSTextField!
|
||||
```
|
||||
|
||||
We already have our Haskell library's header imported, so we
|
||||
can just call the exported `square` function. Add this to
|
||||
`applicationDidFinishLaunching`:
|
||||
With the `SwiftHaskell` module imported and a label connected,
|
||||
let's call `square` and display its result in the label. Add
|
||||
this to `applicationDidFinishLaunching`:
|
||||
|
||||
```swift
|
||||
label.stringValue = "\(square(5))"
|
||||
@@ -401,21 +527,20 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
func applicationWillTerminate(_ aNotification: Notification) {
|
||||
}
|
||||
}
|
||||
|
||||
@_cdecl("swiftAppMain")
|
||||
func swiftAppMain() {
|
||||
let app = NSApplication.shared()
|
||||
var topObjects: NSArray = []
|
||||
NSNib.init(nibNamed: "MainMenu", bundle: Bundle(for: AppDelegate.self))!
|
||||
.instantiate(withOwner: app, topLevelObjects: &topObjects)
|
||||
app.run()
|
||||
}
|
||||
```
|
||||
|
||||
Running the app,
|
||||
|
||||

|
||||
|
||||
If the build fails with `Use of unresolved identifier 'square'`,
|
||||
perform a full clean with the *Product » Clean Build Folder...*
|
||||
⌥⇧⌘K menu command and then rebuild. (Hold ⌥ option to reveal
|
||||
the menu item.) This appears to be a bug with Xcode (version
|
||||
8.2 as of writing) caching some intermediate state from before
|
||||
the `SwiftHaskell` module was fully configured, and should not
|
||||
occur in future builds.
|
||||
|
||||
## Passing Complex Data Types
|
||||
|
||||
### Bytes
|
||||
@@ -743,3 +868,57 @@ class Multiplier {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### `stack build` fails with `ld: framework not found SwiftHaskellLibrary`
|
||||
|
||||
Build the SwiftHaskellLibrary framework in Xcode before running
|
||||
`stack build`.
|
||||
|
||||

|
||||
|
||||
See the discussion about circular dependencies in the *Linking
|
||||
to the Executable* section. If this still fails, ensure that
|
||||
`link-deps.sh` is being run before the framework is built as
|
||||
described at the end of *Linking to the Executable*. Also check
|
||||
that the `build/` directory contains all three symlinks:
|
||||
|
||||
- `SwiftAppLibrary.framework` `-> ~/Library/Developer/Xcode/DerivedData/SwiftHaskell-{hash}/Build/Products/{Debug,Release}/SwiftAppLibrary.framework`
|
||||
- `SwiftHaskell` `-> ../.stack-work/dist/{arch}/Cabal-{version}/build/SwiftHaskell/SwiftHaskell`
|
||||
- `ghc`
|
||||
- `include` `-> ~/.stack/programs/{arch}/ghc-{version}/bin/../lib/ghc-{version}/include`
|
||||
|
||||
### Building in Xcode fails with `PBXCp ...build/SwiftHaskell/SwiftHaskell: No such file or directory`
|
||||
|
||||
Build the Haskell executable with `stack build`.
|
||||
|
||||
### Some Target Membership checkboxes are disabled in Xcode
|
||||
|
||||
Add a Compile Sources or Copy Bundle Resources phase, as
|
||||
appropriate for the file you're modifying, to the target with
|
||||
the disabled checkbox.
|
||||
|
||||
### Building in Xcode fails with `Unable to run command ... - this target might include its own product.`
|
||||
|
||||
Ensure that the Copy Files phase for the executable is copying
|
||||
the executable, and not the app bundle (the product). See the
|
||||
*App Bundle Configuration* section.
|
||||
|
||||

|
||||
|
||||
### Running the app fails with `dyld: Library not loaded: @rpath/libswiftAppKit.dylib`
|
||||
|
||||
Ensure that **Always Embed Swift Standard Libraries** is set
|
||||
to **Yes** on the app target, as described in *App Bundle
|
||||
Configuration*.
|
||||
|
||||

|
||||
|
||||
### Building in Xcode fails with `Use of unresolved identifier 'square'`
|
||||
|
||||
If the module is certainly imported, this is probably from Xcode
|
||||
incorrectly retaining an expired cache for the `SwiftHaskell`
|
||||
module. Perform a full clean with the *Product » Clean Build
|
||||
Folder...* ⌥⇧⌘K menu command and then rebuild. (Hold ⌥ option to
|
||||
reveal the menu item.)
|
||||
|
||||
@@ -37,15 +37,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
@_cdecl("runNSApplication")
|
||||
func runNSApplication() {
|
||||
let app = NSApplication.shared()
|
||||
var topObjects: NSArray = []
|
||||
NSNib.init(nibNamed: "MainMenu", bundle: Bundle(for: AppDelegate.self))!
|
||||
.instantiate(withOwner: app, topLevelObjects: &topObjects)
|
||||
app.run()
|
||||
}
|
||||
|
||||
|
||||
// Swift to Haskell ByteString Example
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#import "SwiftAppLibrary.h"
|
||||
|
||||
@interface AClassInThisFramework : NSObject @end
|
||||
@implementation AClassInThisFramework @end
|
||||
|
||||
void runNSApplication(void) {
|
||||
NSApplication *app = [NSApplication sharedApplication];
|
||||
NSBundle *bundle = [NSBundle bundleForClass:[AClassInThisFramework class]];
|
||||
NSArray *topObjects;
|
||||
[[[NSNib alloc] initWithNibNamed:@"MainMenu" bundle:bundle]
|
||||
instantiateWithOwner:app topLevelObjects:&topObjects];
|
||||
[app run];
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
BFABC4E01E4D781D006036C6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BFABC4DF1E4D781D006036C6 /* Assets.xcassets */; };
|
||||
BFABC4ED1E4D78E5006036C6 /* SwiftHaskell in Copy Files */ = {isa = PBXBuildFile; fileRef = BFABC4EA1E4D78D9006036C6 /* SwiftHaskell */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
BFABC4F01E4D7951006036C6 /* SwiftAppLibrary.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BFABC45B1E4C1DD1006036C6 /* SwiftAppLibrary.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
BFE4CC421E55553000F232D6 /* SwiftAppLibrary.m in Sources */ = {isa = PBXBuildFile; fileRef = BFE4CC411E55553000F232D6 /* SwiftAppLibrary.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -60,6 +61,7 @@
|
||||
BFABC4DF1E4D781D006036C6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
BFABC4E41E4D781D006036C6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
BFABC4EA1E4D78D9006036C6 /* SwiftHaskell */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = SwiftHaskell; path = build/SwiftHaskell; sourceTree = SOURCE_ROOT; };
|
||||
BFE4CC411E55553000F232D6 /* SwiftAppLibrary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SwiftAppLibrary.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -76,8 +78,8 @@
|
||||
BFABC4511E4C1DD1006036C6 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BFABC45D1E4C1DD1006036C6 /* SwiftAppLibrary */,
|
||||
BFABC4D81E4D781D006036C6 /* SwiftHaskell */,
|
||||
BFABC45D1E4C1DD1006036C6 /* SwiftAppLibrary */,
|
||||
BFABC45C1E4C1DD1006036C6 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
@@ -95,6 +97,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BFABC45E1E4C1DD1006036C6 /* SwiftAppLibrary.h */,
|
||||
BFE4CC411E55553000F232D6 /* SwiftAppLibrary.m */,
|
||||
BFABC4CC1E4D627E006036C6 /* AppDelegate.swift */,
|
||||
BFABC4D01E4D664D006036C6 /* MainMenu.xib */,
|
||||
BFABC45F1E4C1DD1006036C6 /* Info.plist */,
|
||||
@@ -197,8 +200,8 @@
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
BFABC45A1E4C1DD1006036C6 /* SwiftAppLibrary */,
|
||||
BFABC4D61E4D781D006036C6 /* SwiftHaskell */,
|
||||
BFABC45A1E4C1DD1006036C6 /* SwiftAppLibrary */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -229,9 +232,9 @@
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(PROJECT_DIR)/src/Lib.hs",
|
||||
"$(PROJECT_DIR)/src/Main.hs",
|
||||
"$(PROJECT_DIR)/SwiftHaskellLibrary.cabal",
|
||||
"$(PROJECT_DIR)/stack.yaml",
|
||||
);
|
||||
name = "stack build and link-deps";
|
||||
outputPaths = (
|
||||
@@ -266,6 +269,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BFABC4CD1E4D627E006036C6 /* AppDelegate.swift in Sources */,
|
||||
BFE4CC421E55553000F232D6 /* SwiftAppLibrary.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -296,10 +300,10 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
@@ -348,10 +352,10 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
@@ -391,7 +395,7 @@
|
||||
BFABC4641E4C1DD1006036C6 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
@@ -419,7 +423,7 @@
|
||||
BFABC4651E4C1DD1006036C6 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "";
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
@@ -446,6 +450,7 @@
|
||||
BFABC4E61E4D781D006036C6 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = SwiftHaskell/Info.plist;
|
||||
@@ -458,6 +463,7 @@
|
||||
BFABC4E71E4D781D006036C6 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
INFOPLIST_FILE = SwiftHaskell/Info.plist;
|
||||
|
||||
|
Before Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |