У меня есть простое приложение gRPC, клиент и сервер. Оба полагаются на сгенерированные привязки swift-grpc. Для простоты, когда я копирую общие файлы один раз в папку клиента и второй раз в папку сервера, Swift создает и запускает оба. По понятным причинам я хочу разделить общие файлы на общую библиотеку, серверную библиотеку и клиентскую библиотеку, чтобы импортировать в клиент только общие и специфичные для клиента библиотеки.
Начиная с моей общей библиотеки под названием DmxLib, я не могу понять файл Package.swift. По сути, в документах говорится: создайте библиотеку, добавьте ее как зависимость, и все готово. Когда я это делаю, сборка Swift не работает, говоря, что импортированных файлов нет. Когда я добавляю локальные файлы из папки DmXLib в зависимости продукта, он говорит мне, что файл не может быть найден.
Редактор — VSCode, а платформа — Ubuntu 20.04 с Swift 5.3, без XCode.
Как правильно объявить общую локальную библиотеку, которую можно импортировать и использовать как на клиенте, так и на сервере?
Мое исходное дерево выглядит так
И мой файл Package.swift
// swift-tools-version:5.2
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "dmx-db",
products: [
.executable(name: "DmxServer", targets: ["DmxServer"]),
.executable(name: "DmxClient", targets: ["DmxClient"]),
// This lib will be imported into both, client and server.
.library(name: "DmxLib", targets: ["DmxLib"]),
],
dependencies: [
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.21"),
.package(url: "https://github.com/codewinsdotcom/PostgresClientKit", from: "1.0.0"),
.package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "1.0.0-alpha.5"),
// Why do I have to declare local files as dependencies???
.package(path: "../Sources/DmxLib/datasource.grpc.swift")
],
//
targets: [
.target(name: "DmxLib", dependencies: [
"datasource.grpc.swift"
] ),
.target(name: "DmxServer", dependencies: [
"DmxLib",
.product(name: "GRPC", package: "grpc-swift"),
.product(name: "PostgresClientKit", package: "PostgresClientKit"),
.product(name: "Lifecycle", package: "swift-service-lifecycle"),
]),
.target(name: "DmxClient", dependencies: [
"DmxLib",
.product(name: "GRPC", package: "grpc-swift"),
]),
]
)
Это должно сделать это. Вам не нужно добавлять «зависимость» к цели, где все источники находятся на вашем локальном компьютере.
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "dmx-db",
products: [
.executable(name: "DmxServer", targets: ["DmxServer"]),
.executable(name: "DmxClient", targets: ["DmxClient"]),
// This lib will be imported into both, client and server.
.library(name: "DmxLib", targets: ["DmxLib"]),
],
dependencies: [
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.21"),
.package(url: "https://github.com/codewinsdotcom/PostgresClientKit", from: "1.0.0"),
.package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "1.0.0-alpha.5"),
],
targets: [
.target(name: "DmxServer", dependencies: [
"DmxLib",
.product(name: "GRPC", package: "grpc-swift"),
.product(name: "PostgresClientKit", package: "PostgresClientKit"),
.product(name: "Lifecycle", package: "swift-service-lifecycle"),
]),
.target(name: "DmxClient", dependencies: [
"DmxLib",
.product(name: "GRPC", package: "grpc-swift"),
]),
.target(name: "DmxLib", dependencies: []),
]
)
Для этого требуется, чтобы у вас был каталог Sources
в корневом каталоге вашего пакета, а внутри него у вас были три папки с именами DmxLib
, DmxClient
и DmxServer
соответственно.
Примечание. На самом деле я обновил swift-tools-version
до 5.3, потому что я скопировал и изменил это из одного из моих проектов, но я думаю, что он должен работать с swift-tools-version
5.2.
для LOCAL мы страдаем из-за плохого Xcode UI/UX..
(в моем примере у меня есть SPM, «LocalSPMLib» и потребительское приложение, «LocalSPMConsumerApp»)
Вы можете сделать таким образом:
он добавит в проект, но не будет работать... Должен отображаться в двоичных файлах, но НЕ ;(
Теперь вы можете вызывать:
import XCTest
import LocalSPMLib
@testable import LocalSPMConsumerApp
class LocalSPMConsumerAppTests: XCTestCase {
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() throws {
XCTAssertEqual(LocalSPMLib().version, 1)
}
}