Package Loading: "Ignoring duplicate product" (SwiftPM) - swift

I'm trying to build a Swift package using the Swift Package Manager.
However, when I open the package in Xcode and click Run, I get the following warning:
How can I resolve this?

This is an issue often encountered if you are attempting to build a library/framework but also have a main.swift file in your target's root directory, like so:
.
The presence of a main.swift file makes SwiftPM believe that you are attempting to build a command line tool, and thus complains about the unnecessary (duplicate in name) library produced.
This warning may be confusing as it does not occur in projects initialized with the dynamic framework template from Xcode, for iOS, macOS, tvOS or watchOS.

In my case it was because I had the same name in both the products section and the Package e.g.
let package = Package(
name: "Example",
products: [
.library(
name: "Example",
targets: ["Example"]),
],
)
This seems to be the default behavior of swift init for some reason. I removed the .library entry and the warning went away.

Related

Swift update deployment target to match package requirement

I'm new to swift development, so excuse the basic question, but when I import a package called SwiftHttp in a local package, I get this error:
Compiling for macOS 10.13, but module 'SwiftHttp' has a minimum deployment target of macOS 10.15:
So I've gone in to my project's setting, and changed the minimum deployments to macOS 11.0, both in the "project" section, and for all targets, but that error remains in the file. Is there anywhere else I need to update that setting? Or is there something I need to do to "propagate" that setting to the local package?
Images of what I have...
Project settings:
Target settings
Error:
I managed to fix it by explicitly setting a supported platform version in package.swift in my own package, which I use" in this project. The relevant part now looks like this:
let package = Package(
name: "Swiftodon",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6)
],

No such module in a Swift Package using Xcode - package listed in dependencies

I create a blank template package:
> swift package init --name Temp
> open Package.swift
Xcode Version 13.2.1 (13C100) opens the package.
I add a dependency to the package.
dependencies: [
.package(url: "https://github.com/johnsundell/publish.git", from: "0.7.0")
],
Xcode > Product > Build succeeds at this point.
I edit Temp/Sources/Temp/Temp.swift to insert the first line the package that is defined in dependencies.
import Publish
A build now generates the following error:…/Temp/Sources/Temp/Temp.swift:1:8: error: no such module 'Publish'.
I feel certain this is an Apple bug. Or I could be missing something.
There are several posts about this problem when there is an xcodeproj and the additional structure that provides. Some of them hint at workarounds that help some people.
Has anyone seen this and/or know of how to resolve it?
Apple's Creating a Standalone Swift Package with Xcode document doesn't provide any insight.
thanks for the chatter in the comments, #Larme & #koen, it helped
The issue was user error (and/or a documentation lapse). Living on the (bleeding) edge.
Sometimes updates from changes are slow or require a clean or a relaunch.
Xcode auto-generates Schemes from the targets defined in your package. My build was targeting MyTarget.
Two things were missing:
name: "Publish" was not included in the package dependency - it's needed so you can reference it below (or maybe this can be derived, it's hard to tell because of Xcode refresh issues), and
a reference is needed in the dependencies for each target using the package-dependency, i needed to add dependencies: ["Publish"] in the related target
dependencies: [
.package(name: "Publish", url: "https://github.com/johnsundell/publish.git", from: "0.7.0")
],
…
targets: [
.target(
name: "MyTarget",
dependencies: ["Publish"]),
]

How to generate a framework from a SwiftPM-generated XCode project?

I used SwiftPM to set up an XCode project for a framework; based on
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "MyThing",
products: [
.library(
name: "MyThing",
targets: ["MyThing"]),
],
dependencies: [
],
targets: [
.target(
name: "MyThing",
dependencies: [])
)
I ran swift package generate-xcodeproj and then pod install (based on a Podfile whose content shouldn't matter). I obtain MyThing.xcworkspace.
Now I figured that
xcodebuild -workspace MyThing.xcworkspace -scheme MyThing clean build
should create the .framework -- but it doesn't, only a binary file appears. I suspect some automatism is at work here since the source folder contains a file named main.swift, among others.
What do I have to do to get the framework built?
I need to script the whole process, to please no manual workarounds.
As of Swift 4.0 swift package generate-xcodeproj doesn't automatically generate schemes for all targets, but still makes those targets accessible from Xcode.
If creating a new scheme manually once is acceptable, you can do so and add your framework target as a scheme build target.
Otherwise, new schemes can be created programmatically with libraries like xcodeswift/xcproj, which allow you to parse a newly generated Xcode project and generate a new scheme with its XCSharedData class.
After that new framework scheme is created you can run the build with xcodebuild -workspace MyThing.xcworkspace -scheme MyThingFramework clean build.
Mixing script files and framework code in one target seems to confuse SwiftPM. Moving main.swift out of the source folder clears up things.
Scheme MyThing-Package creates all build products as specified in Package.swift, including the framework.
If you want to have the script files in the same XCode Workspace (for editing convenience), put them in their own target. You can even create an executable product (which won't create anything useful since an executable can't link to dynamic frameworks).

Importing modules with Swift package manager

I am trying to use Swift's package manager to import external modules in my project. My first module come from the Vapor project. I cannot seem to get it working. I start with
swift package init
swift package generate-xcodeproj
My Package.swift looks like this:
import PackageDescription
let package = Package(
name: "OpenTools",
products: [
.library(
name: "OpenTools",
targets: ["OpenTools"]),
],
dependencies: [
.package(url: "https://github.com/vapor/json.git", from: "2.0.0")
],
targets: [
.target(name: "OpenTools", dependencies: ["JSON"]),
]
)
I then run
swift package update
swift package generate-xcodeproj # to regenerate with dependencies
and then try to import the JSON package in my main file
import JSON
The modules are there as shown below but the import gets back with an No such module 'JSON' error.
Any thoughts?
Probably the problem lies within Xcode, as it does not know yet that JSON exists, because it was not built yet. This can easily be solved by just building your project (with cmd-B). With the generated xcodeproj, Xcode should know that it first needs to build JSON and then the rest, because JSON is marked as a dependency for your target.
You can check this, by navigating in Xcode to your target (when you click on the project description file) and afterwards to "Build Phases". Under Target Dependencies you should find your JSON module.
In addition you should find a JSON module under your targets, which compiles the sources you gathered from github.
Your project should also build when executing swift build in your project root.
With Xcode 11 you should be able to open Package.swift directly which will give you a proving ground for verifying the package manifest (aka: the Package.swift file) and compiling the target. This should help see what is actually causing the error that's preventing the module from being compiled.

Where to create your own file in Vapor?

I just tried to create a web app using Vapor, but when I tried to define my own variable/constant in my project, and write it in main.swift, the following error occurred.
let websiteURL = "http://localhost:8080" // in AppConstants.swift
let url = websiteURL // in main.swift
Use of unresolved identifier: websiteURL
However, it seems that the PostController class defined in Controllers directory can be seen without any problems. I put AppConstants.swift in the same directory as main.swift, but it got the error above.
In traditional iOS/macOS app, which is the only project I have developed so far, if you just create any files in the project, they can be seen from anywhere in the project, I think.
So how and where can I create and define my custom file in Vapor?
UPDATE
Here is my Package.swift file in my project:
import PackageDescription
let package = Package(
name: "vapor_sample",
dependencies: [
.Package(url: "https://github.com/vapor/vapor.git", majorVersion: 1, minor: 0)
],
exclude: [
"Config",
"Database",
"Localization",
"Public",
"Resources",
"Tests",
]
)
UPDATE 2
I found that for some reasons, the default files created by Vapor are named with directory suffix, like Controllers/PostController.swift, not PostController.swift. I tried moving AppConstants.swift under the directory, but it doesn't show its file name with the directory suffix. Is there anything related to it? I use Xcode 8.0.
Xcode projects associated w/ SwiftPM and Server Side Swift generally tend to be a bit finicky. You should regen as often and as regularly as possible. Also cleaning and deleting derived data never hurts. Here's some situations you might want to regen:
New File
Changed File Name
New Folder
New Package
Change Package Version
Feel like it
Basically, anytime anything goes wrong in Xcode, and you don't know where to start. Clean, Delete Derived, Regen.