我正在Linux上编写一些入门级的swift代码作为学习练习。
作为一般任务,我希望在我自己的代码中使用第三方Swift模块。我们称这个模块为“Foo”。 Foo模块有一个Package.swift文件,在该目录中运行swift build
之后,它创建了.build/debug/libFoo.so
。
现在我想做两件事:
import Foo
。我觉得这两项任务都是相关的,所以现在它们都是同一个问题。
对于1.,我不明白包裹如何被REPL“找到”。我试过swift -F .build/debug -framework Foo
,但我得到了“没有这样的模块”错误。我也尝试了swift -I .build/debug
同样的结果。
对于2.,我检查了swiftc --help
并且有-L
和-l
个选项但是我无法找到使用这些选项的正确方法:
$ swiftc main.swift -L ../foo.git/.build/debug -llibFoo.so
main.swift:1:8: error: no such module 'Foo'
import Foo
^
我正在使用Swift 2.2或3.0(使用swim
而不是swift build
用于2.2,因为没有swift build
- 但它产生相同的输出我相信)。
请注意,我理解swift build
可以自动下载和构建第三方模块,但我想知道如何合并磁盘模块,因为它们可能是我自己的工作进度模块。< / p>
编辑:我尝试使用swift3进行一些实验,基于一个发现,你可以使用本地路径作为Package url:
列表中的dependencies:
参数,至少对于本地开发而言。
我创建了一个目录Bar
和Bar/Package.swift
:
import PackageDescription
let package = Package(name: "Bar")
我还创建了Bar/Sources/bar.swift
,其中包含:
public func bar(arg: Int) -> Int {
return arg * 2
}
目的是模块Bar
提供名为bar(arg:)
的函数。
我做了git init
,git add .
,git commit -m "Initial commit."
,然后git tag 1.0.0
为此模块创建了一个标记为的本地 git repo。
然后回到顶层,我创建了目录Foo
和Foo/Package.swift
:
import PackageDescription
let package = Package(
name: "Foo",
dependencies: [ .Package(url: "../Bar", majorVersion: 1) ]
)
请注意../Bar
的相对路径。
我还创建了Foo/Sources/main.swift
:
import Bar
print(bar(arg: 11))
现在当我在swift build
内Foo
时,它会克隆Bar
并构建它。然而,我得到以下错误; 没有这样的模块:
$ swift build
Compile Swift Module 'Bar' (1 sources)
Compile Swift Module 'Foo' (1 sources)
.../Foo/Sources/main.swift:1:8: error: no such module 'Bar'
import Bar
^
<unknown>:0: error: build had 1 command failures
error: exit(1): .../swift-3.0-PREVIEW-4-ubuntu14.04/usr/bin/swift-build-tool -f .../Foo/.build/debug.yaml
奇怪的是,如果我再次执行完全相同的构建命令,我会得到一个不同的错误:
$ swift build
Compile Swift Module 'Foo' (1 sources)
Linking .build/debug/Bar
.../Foo/Sources/main.swift:3:7: error: use of unresolved identifier 'bar'
print(bar(arg: 11))
^~~
<unknown>:0: error: build had 1 command failures
error: exit(1): .../swift-3.0-PREVIEW-4-ubuntu14.04/usr/bin/swift-build-tool -f .../Foo/.build/debug.yaml
我曾希望这可行。
答案 0 :(得分:3)
能够在我自己的swift程序中导入Foo,可能是通过链接这个共享对象。
使用您在“编辑”之后在问题中发布的示例,如果您使用swift build
,这似乎可以正常工作。 Swift Package Manager将为您处理所有依赖项,即使它们是在磁盘上(这适用于Swift 3和4):
$ cd Foo
$ swift build
Cloning /path/to/Bar
HEAD is now at 0c3fd6e Initial commit.
Resolved version: 1.0.0
Compile Swift Module 'Bar' (1 sources)
Compile Swift Module 'Foo' (1 sources)
Linking ./.build/debug/Foo
$ .build/debug/Foo
22
请注意,Foo / .build / debug不包含任何.so文件:
$ ls Foo/.build/debug
Bar.build Bar.swiftdoc Bar.swiftmodule Foo Foo.build Foo.swiftdoc Foo.swiftmodule ModuleCache
我相信会使用.swiftdoc和.swiftmodule文件。
能够在REPL中导入Foo。
这部分有点麻烦,但我找到了解决方案here。要将其应用于您的示例,您有两个选择:
Use swift build
with extra flags(适用于Swift 3和4):
$ cd Bar
$ swift build -Xswiftc -emit-library
Compile Swift Module 'Bar' (1 sources)
$ swift -I .build/debug -L . -lBar
1> import Bar
2> bar(arg: 11)
$R0: Int = 22
3>
这会在当前目录中创建libBar.so:
$ ls
libBar.so Package.swift Sources
Update your Package.manifest(这是特定于Swift 4):
更新的Package.manifest看起来像这样:
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "Bar",
products: [
.library(
name: "Bar",
type: .dynamic,
targets: ["Bar"]),
],
targets: [
.target(
name: "Bar",
dependencies: [],
path: "Sources"),
]
)
这就是你如何进行构建并调用REPL:
$ cd Bar
$ swift build
Compile Swift Module 'Bar' (1 sources)
Linking ./.build/x86_64-unknown-linux/debug/libBar.so
$ swift -I .build/debug -L .build/debug -lBar
1> import Bar
2> bar(arg: 11)
$R0: Int = 22
3>
这会在.build / debug目录中创建libBar.so:
$ ls .build/debug
Bar.build Bar.swiftdoc Bar.swiftmodule libBar.so ModuleCache
如果您无法重现这些结果,我建议清理所有.build目录和.so文件,并安装一个干净版本的Swift(我建议swiftenv)。
答案 1 :(得分:1)
正如文档中所述,Linux上的Swift及其软件包管理器正在进行中,因此难怪存在缺陷和缺少信息。然而,这是我通过实验和阅读帮助找到的。
如果模块Foo
在libFoo.so
中有/LibLocation
,Foo.swiftmodule
中有/ModuleLocation
,则可以导入并使用{{} 1)在Swift程序中,将其命名为Foo
,然后通过执行
main.swift
也可以通过将其作为
启动来在REPL中完成swiftc -I /ModuleLocation -L /LibLocation -lFoo main.swift
即。基本上给它与swift -I /ModuleLocation -L /LibLocation -lFoo
相同的论点。顺便说一句,如果模块是使用swiftc
构建的,则swift build
可能与ModuleLocation
相同。
正如我在之前的评论中提到的那样,使用LibLocation
生成的Foo
和Bar
的示例,对我来说都很合适,所以我无法重现问题。< / p>
除了阅读swift.org文档和命令行帮助之外,通过运行swift build
和其他带有swift build
标志的命令,可以收集大量有趣且可能有用的信息。要了解-v
的一些隐藏选项,请执行
swiftc