Hi there! --
This is my first time posting on the Swift Forums, but I've been following the discussions for quite some time now, and I find everything you say and share to be an infinite resourceful mine of learning opportunities.
The reason I'm posting today is that there is something I cannot get my head around regarding naming products and targets in Package.swift
and the subsequent import
statements in the code.
The situation
I have two packages:
-
SwiftPM_Libs
- a library package containing 3 independent libraries inSources
-Lib1
,Lib2
andLib3
-
SwiftPM_Exec
- an executable package importingSwiftPM_Libs
as a dependency
Both packages are available here if you want to try for yourself. Clone them in the same directory.
Now here are the directory structure and the Package.swift
of both packages:
SwiftPM_Libs
Tree structure
.
βββ Package.swift
βββ README.md
βββ Sources
β βββ Lib1
β β βββ SwiftPM_Lib1.swift
β βββ Lib2
β β βββ SwiftPM_Lib2.swift
β βββ Lib3
β βββ SwiftPM_Lib3.swift
βββ Tests
Package.swift
// swift-tools-version:4.2
import PackageDescription
let package = Package(
name: "SwiftPM_Libs",
products: [
.library(name: "LibName1", targets: ["Lib1"]),
.library(name: "LibName2", targets: ["Lib2"]),
.library(name: "LibName3", targets: ["Lib3"]),
.library(name: "LibNameAllLibs", targets: ["Lib1", "Lib2", "Lib3"]),
],
targets: [
.target(name: "Lib1", dependencies: []),
.target(name: "Lib2", dependencies: []),
.target(name: "Lib3", dependencies: []),
]
)
SwiftPM_Exec
Tree structure
.
βββ Package.resolved
βββ Package.swift
βββ README.md
βββ Sources
β βββ SwiftPM-Exec
β βββ main.swift
βββ Tests
Package.swift
// swift-tools-version:4.2
import PackageDescription
let package = Package(
name: "SwiftPM_Exec",
dependencies: [
.package(path: "../SwiftPM_Libs"),
],
targets: [
.target(name: "SwiftPM-Exec", dependencies: ["LibName1"]),
]
)
What is happening
Now let's say, I am only interested in the classes/functions provided by LibName1
, I add the following .target(name: "SwiftPM-Exec", dependencies: ["LibName1"]),
to my targets: []
.
Now in my code, I would expect to import LibName1
as it is the one I'm referring to in my target's dependencies.
But this doesn't work. Instead I need to import Lib1
which is the name of the target used by the product .library(name: "LibName1", targets: ["Lib1"]),
in the SwiftPM_Libs's Package.swift
.
This is okay as long as my directories, targets and products have the same name.
What I thought would be happening
My idea was that I could have complexe directory structure, custom target names for internal use, and then expose the result to an outside user through a product and its name. I would expect the final user to have access to my libraries by simply importing the dependency and not having to import all the targets needed by that dependency.
The product .library(name: "LibNameAllLibs", targets: ["Lib1", "Lib2", "Lib3"])
is a good example of that.
I would expect that using .target(name: "SwiftPM-Exec", dependencies: ["LibNameAllLibs"])
would let me import LibNameAllLibs
to access them.
I've also tried defining my targets with path:
and sources:
but it complains about overlapping sources.
Conclusion
Maybe I'm doing something wrong, maybe what I'm doing is an edge case. And in the case I would thankful if you could point me to the right direction.
On the other hand, I think granularity is good thing for package developers, but that for package users, they should only be interested in the package's products and not in the maybe multiple targets used internally by the package.
Is that something "interesting" that could be on the roadmap?
Thanks a lot for your kind help!
Best,
-- Ladislas