I want to configure Package.swift so that one target would be an extension to another, both of them should share the same code from the one folder, but for the "extended" version there is an additional subfolder. But configuration I try with path fails with "overlapping sources" error. So, how can I make two target with the same source folder?
.target(name: "App", dependencies: [ "Vapor" ... ], exclude: [ "Subfolder" ])
.target(name: "Extended", dependencies: [ "Vapor", ... ], path: "./Sources/App")
swift build ... error: target 'Extended' has sources overlapping sources...
SwiftPM is strict about one target gets to own the files. So you will need to set up a proper dependency chain for your files.
It sounds like Extended adds more functionality to App in this case. If so you want to have App all the things it currently is. Then have Extended depend on App and build all of the things exclusive to it.
This allows 1 target to own the source files and allows Extended to use the one implementation of those files.
In my case I had one of my executableTargets path set to the root "."
.executableTarget(
name: "ServiceA",
dependencies: [Vapor..],
path: "."),
.executableTarget(
name: "ServiceB",
dependencies: [Vapor..]),
After I removed the path from the constructor in ServiceA. I was able to set the proper folders and Xcode was able to infer the path of my executable targets
Sources
|_ServiceA
|_ServiceB
.executableTarget(
name: "ServiceA",
dependencies: [Vapor..])
.executableTarget(
name: "ServiceB",
dependencies: [Vapor..]),
Related
Is it possible for a Local Swift Package to depend on a Xcode Project (that creates a xcframework) in the same workspace?
I have tried things in the targets section in Package.swift file to point to the path where the local Xcode project is.
targets: [
.target(
name: "SomeJourney",
dependencies: ["OurUIFramework"]),
.binaryTarget(name: "OurUIFramework", path: "../../Frameworks/OurUIFramework")
]
I'd like to create a SwiftPackageManager library based on Objective-C code but I can't seem to grasp what I'm missing.
My latest change to just vanilla ObjC interface .h file inside the include folder was to add an extra C header that includes de ObjC but still had no success. What am I missing?
The Package.swift file is the default generated one and from what I read it should automatically generate the module map from the include folder.
My swift-tools-version is 5.5
Figured it out.
I added a modulemap that specifies my ObjC header and it worked
Not sure if it is the correct way to do it since the include folder should already do this automatically.
So just had the same issue. (my 5 cent)
This is may Package.swift:
// swift-tools-version: 5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "AlgorithmSDK",
platforms: [
.iOS(.v13)
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages. , "AlgorithmSDKObjc"
.library(
name: "AlgorithmSDK",
targets: ["AlgorithmSDK","AlgorithmSDKObjc" ]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "AlgorithmSDK",
dependencies: []),
.testTarget(
name: "AlgorithmSDKTests",
dependencies: ["AlgorithmSDK"]),
.target(
name: "AlgorithmSDKObjc",
dependencies: [],
publicHeadersPath:"include"),//<----- This path is relative to the target! (and can be ignored)
]
)
With the structure:
The publicHeadersPath should be publicHeadersPath:"include" OR ignored according to docs (it seems that it takes it relative to target and not the root). I don't think we should touch module.modulemap for such a simple structure
I am creating a Swift Package that is essentially a wrapper for multiple XCFrameworks generated from Objective-C frameworks so they can be installed via SPM.
Everything works fine as far as creating the SP and ability to add it as a dependency to an app. But I have a bunch non-essential files included in the SP's repository that I don't want to include in the actual SP - i.e. They shouldn't show up in Xcode's navigator when the SP is added as a dependency.
(These consist of the source Obj-C Frameworks, README, Changelog, Xcode Workspace for demo app, Script files for generating the XCFrameworks, etc).
Is this even possible?
Or will SPM always checkout the entire repo and make all files visible to the user?
I have tried using various permutations of the Target specifiers: source, path, exclude but to no avail.
Here is the closest I can get with a valid manifest, but when I check out the SP in a dummy Xcode app, I can still see all the files from the repo included:
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "WrapperSwiftPackage",
platforms: [.iOS(.v13)],
products: [
.library(name: "WrapperSwiftPackage", targets: ["WrapperSwiftPackage"])
],
dependencies: [],
targets: [
.target(
name: "WrapperSwiftPackage",
dependencies: [
"ObjCFramework1",
"ObjCFramework2"
],
path: "", // Set to root directory so we can exclude files below
exclude: [
"CHANGELOG.md",
"Dangerfile.swift",
"README.md",
"Workspace.xcworkspace",
"Scripts/generate-xcframework.sh",
"Scripts/link_git_hooks.sh",
"Objective-C Frameworks/"
],
sources: [
"Sources/WrapperSwiftPackage/main.swift",
"XCFrameworks/ObjCFramework1.xcframework",
"XCFrameworks/ObjCFramework2.xcframework"
]
),
.binaryTarget(name: "ObjCFramework1", path: "XCFrameworks/ObjCFramework1.xcframework"),
.binaryTarget(name: "ObjCFramework2", path: "XCFrameworks/ObjCFramework2.xcframework")
]
)
Not sure if that isn't a bug though, but I've accidentaly came up to one solution for this.
If you put an empty Package.swift (I mean, one like this):
// swift-tools-version:5.5
import PackageDescription
let package = Package()
into one of project subfolders, then even though SPM is checking the subfolder out, it's excluded from Xcode navigator, and thus, from the project visibility.
I would like to know if that's a bug or is it documented somewhere, every hint is appreciated.
Works with local and remote dependencies.
I'm writing a Swift script as a standalone Swift Package. Part of this script needs to generate some files, for which I have templates.
Now, these templates are not compilable (they're HTML files); so in order to include them in the package I've included them as .copy("Templates").
When debugging my script, I can access the templates just fine, but when I try to archive the product, the executable doesn't have access to them anymore.
Here's my Package.swift:
let package = Package(
name: "flucs",
products: [
.executable(name: "Flucs",
targets: ["flucs"])
],
dependencies: [
.package(url: "https://github.com/MrSkwiggs/Netswift", .exact(.init(0, 3, 1))),
],
targets: [
.target(
name: "flucs",
dependencies: ["Netswift"],
path: "Sources",
resources: [
.copy("Templates")
]),
.testTarget(
name: "flucsTests",
dependencies: ["flucs"]),
]
)
My folder structure:
How can I distribute my script so that it also includes its resources?
SPM compiles your resources to a separate bundle but command line tool is just an executable without a bundle and any resources you add to your executable is simply ignored by Xcode (Build Phases > Copy Bundle Resources) for Release(Archive) builds.
If you look inside Bundle.module you can find:
...
// For command-line tools.
Bundle.main.bundleURL,
...
Where Bundle.main.bundleURL is a valid file url for the directory containing your command line executable so that it looks for your bundle next to your executable. And it works for Debug because XCode just compiles your resource bundle near your executable.
The simplest way to get Release executable with compiled .bundle file is build your package from command line:
swift build --configuration release
And then you can find them both in .build/release folder.
I'm trying to compile using swift build
Package.swift
// swift-tools-version:4.2
// The swift-tools-version declares the minimum version of Swift required to build this package.
// swift-tools-version:x.x
import PackageDescription
let package = Package(
name: "MyKituraApp",
dependencies: [
.package(url: "https://github.com/IBM-Swift/Kitura", from: "2.7.0")
],
targets: [
.target(
name: "MyKituraApp",
dependencies: ["Kitura"],
path: "Sources"),
.testTarget(
name: "MyKituraAppTests",
dependencies: ["MyKituraApp"],
path: "Test")
]
)
But, I get the following error although I did add the path property.
'MyKituraApp' /src: error: could not find source files for target(s): MyKituraAppTests; use the 'path' property in the Swift 4 manifest to set a custom target path
Without knowing your project structure I can't give you a definite answer but I'll do my best!
I'm going to assume you've generated your project using the Swift Package Manager tool, something like this:
swift package init --type executable
So... Typically you shouldn't need to set the path property unless you've moved the tests for your application to another directory. The Swift Package Manager, by default, will create a Tests directory and when you do not provide a value for the path property the Swift Package Manager will look for that Tests directory by default when you run swift build. In your path property you are providing a value of Test not Tests
So my first solution to test would be:
To remove the path property from the .testTarget section
OR
Rename the path properties value to Tests rather than Test.
I've provided an example Package.swift that I was able to run swift build with:
// swift-tools-version:4.2
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MyKituraApp",
dependencies: [
.package(url: "https://github.com/IBM-Swift/Kitura", from: "2.7.0")
],
targets: [
.target(
name: "MyKituraApp",
dependencies: ["Kitura"],
path: "Sources"),
.testTarget(
name: "MyKituraAppTests",
dependencies: ["MyKituraApp"])
]
)
As you can see I've also removed an extra line from the top of the file:
// swift-tools-version:x.x
You've already provided a swift-tools-version at the top of your file, this line may end up confusing things later down the line.
I hope this helps!