Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I import a swift function declared in a compiled .swiftmodule into another swift file?

Tags:

swift

Is there a way to declare a function in a .swift file (that is compiled into a .swiftmodule), like so:

hello.swift

func hello_world() {
    println("hello world")
}

main.swift

import hello

hello.hello_world()

I've also made a git repo with these two files and a Makefile with the compile / link commands ready to go. Currently I can get main.swift to import hello, but it's currently failing to link ... is there another linker flag I can pass? Currently Makefile is:

PWD=$(shell pwd)
APP_NAME=main
MODULE_NAME=hello
SWIFT_MODULE_PATH=$(PWD)/$(MODULE_NAME).swiftmodule
SDK=/Applications/Xcode6-Beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk


main : clean
xcrun swift $(MODULE_NAME).swift -emit-module -v
xcrun swift $(APP_NAME).swift \
    -o $(APP_NAME) \
    -sdk $(SDK) \
    -I $(PWD) \
    -Xlinker -sectalign \
    -Xlinker __SWIFT \
    -Xlinker __ast \
    -Xlinker 4 \
    -Xlinker -sectcreate \
    -Xlinker __SWIFT \
    -Xlinker __ast \
    -Xlinker $(SWIFT_MODULE_PATH) \
    -v
like image 411
prairiedogg Avatar asked Jun 18 '14 23:06

prairiedogg


3 Answers

The .swiftmodule describes the Swift module's interface but it does not contain the module's implementation. A library or set of object files is still required to link your application against. Here's a modified version of the makefile that creates both libhello.dylib and hello.swiftmodule and builds the application against them:

PWD=$(shell pwd)
APP_NAME=main
MODULE_NAME=hello
LIB_NAME=lib$(MODULE_NAME).dylib
LIB_PATH=$(PWD)/$(LIB_NAME)
SWIFT_MODULE_PATH=$(PWD)/$(MODULE_NAME).swiftmodule

main : clean
    xcrun swift \
        -emit-library \
        -o $(LIB_PATH) \
        -Xlinker -install_name \
        -Xlinker @rpath/$(LIB_NAME) \
        -emit-module \
        -emit-module-path $(SWIFT_MODULE_PATH) \
        -module-name $(MODULE_NAME) \
        -module-link-name $(MODULE_NAME) \
        -v \
        $(MODULE_NAME).swift
    xcrun swift $(APP_NAME).swift \
        -o $(APP_NAME) \
        -I $(PWD) \
        -L $(PWD) \
        -Xlinker -rpath \
        -Xlinker @executable_path/ \
        -v


clean :
    rm -rf $(APP_NAME) $(LIB_NAME) $(MODULE_NAME).swiftmodule $(MODULE_NAME).swiftdoc

In the absence of documentation I can't say that this is entirely correct, but it works.

Note that if you simply want to use multiple source files within your application module this is much more straightforward and requires no import declaration or module qualification in main.swift:

swift -o main hello.swift main.swift
like image 107
Matt Stevens Avatar answered Nov 17 '22 06:11

Matt Stevens


You don't actually have to import files in swift at the moment. Because all files are public to your program, you can call methods with a simple let helloSwift = hello You are defining a constant named helloSwift which is used as global hello. Of course, you cant just declare this without a class or a struct, but that is a whole other lesson. Just know that instead of importing, you use let.

like image 1
elito25 Avatar answered Nov 17 '22 06:11

elito25


To generate .so file in Linux using swift build, you can create a shell script file called e.g. build, and its content as:

#!/bin/bash
swift build -Xswiftc -emit-library -Xswiftc -o -Xswiftc libhello.so
like image 1
Amr Avatar answered Nov 17 '22 06:11

Amr