Lance Pollard
Lance Pollard

Reputation: 79248

How to compile Swift from command line

I have these 3 files:

index.swift

import Cocoa

print("Init")
let app = NSApplication.shared()
let delegate = AppDelegate()  // alloc main app's delegate class
app.delegate = delegate      // set as app's delegate
app.run()
print("End")

src/delegate.swift

import Cocoa

class AppDelegate: NSObject, NSApplicationDelegate {
    var newWindow: NSWindow?
    var controller: ViewController?

    override init() {
        print("App")
        super.init()
        mainView()
    }

    func mainView() {
        print("View")
        newWindow   = NSWindow(contentRect: NSMakeRect(10, 10, 200, 200), styleMask: [.titled, .resizable, .closable], backing: .buffered, defer: false)
        let content = newWindow!.contentView! as NSView
        controller  = ViewController()
        //controller?.loadView()
        let view = controller!.view
        content.addSubview(view)
        newWindow!.makeKeyAndOrderFront(nil)
    }

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        print("Launch")  // Not showing this?
    }

    func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
        print("Bye")
        return true
    }
}

src/controller.swift

import Cocoa

class ViewController : NSViewController {
    var name = "Main"
    var button: NSButton?

    @IBAction func onClick(_: Any) {
        print("Click")
    }

    override func loadView() {
        print("Load")
        let view = NSView(frame: NSMakeRect(0,0,200,200))
        view.wantsLayer = true
        view.layer?.borderWidth = 2
        view.layer?.borderColor = NSColor.red.cgColor
        button = NSButton(frame: NSMakeRect(20, 20, 100, 32))
        button?.title = "Click Me"
        button?.target = self
        button?.action = #selector(onClick)
        view.addSubview(button!)
        self.view = view
    }
}

I tried compiling it like this:

swift index.swift src/delegate.swift src/controller.swift

But get this error:

index.swift:7:16: error: use of unresolved identifier 'AppDelegate'
let delegate = AppDelegate()  // alloc main app's delegate class
               ^~~~~~~~~~~
Foundation.PortDelegate:1:17: note: did you mean 'PortDelegate'?
public protocol PortDelegate : NSObjectProtocol {
                ^
CoreText.CTRunDelegate:1:14: note: did you mean 'CTRunDelegate'?
public class CTRunDelegate {
             ^
<unknown>:0: warning: 'cacheParamsComputed' is deprecated
<unknown>:0: warning: 'cacheAlphaComputed' is deprecated
<unknown>:0: warning: 'keepCacheWindow' is deprecated
<unknown>:0: error: 'memoryless' is unavailable
Metal.MTLCommandBufferError:55:14: note: 'memoryless' has been explicitly marked unavailable here
        case memoryless
             ^

Wondering how to get this compiling. Basically, I only need to know how to require/import these classes AppDelegate and ViewController from where they are currently defined into the scope of index.swift. If I place all the code into 1 file index.swift, then it compiles fine. But I would like to modularize it like you do in XCode, but without invoking XCode. Wondering if this can be solved with a plist of some sort. I tried swift -F and swift -I to specify import directories, but no go.

Upvotes: 8

Views: 16736

Answers (1)

As @MartinR said, swiftc is the compiler. Your swift command invokes the interpreter, not the compiler. I think the interpreter can only run a single file.

I've only skimmed the following pages, but they may help you run a Swift program consisting of multiple files.

  1. Use a simple shell script to merge all files into one and run the merged file through the swift interpreter:
  1. Use built-in Swift tools:

I found these (and many similar) pages by searching: swift command line run multiple files

Upvotes: 7

Related Questions