What’s the right way to create a command line tool using ArgumentParser? `swift package` or Xcode create Mac command line tool project?

I believe the right way to create an ArgumentParser command line tool is:

swift package init --type tool --name MyTool

Then open Package.swift in Xcode. But then I cannot add this package:

The “My Mac" target disappeared when dependency is added.

When I create macOS command line tool project from inside Xcode, I can andd the spinner package annd use it. If I add ArgumentParser, running crash.

What should I do?

1 Like

Works for me. I created the tool via swift package init then opened in it Xcode, edited the package manifest and used Spinner in the tool and it compiled and ran OK....

// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "MyTool",
    dependencies: [
        .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.0"),
		.package(url: "https://github.com/dominicegginton/Spinner", from: "1.0.0"),
	],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .executableTarget(
            name: "MyTool",
            dependencies: [
				.product(name: "ArgumentParser", package: "swift-argument-parser"),
				.product(name: "Spinner", package: "Spinner"),
            ]
        ),
    ]
)

Thank you for your test! I should have tried using Spinner package on a brand new project. As you've verified, adding Spinner dependency works fine on newly a created project.

However, my problem occur when I add Spinner dependency to my existing project. But knowing Spinner does indeed works fine, so I look at the error closely and it's dependency conflict:

Failed to resolve dependencies Dependencies could not be resolved because root depends on 'rainbow' 4.0.1..<5.0.0 and root depends on 'spinner' 1.0.0..<2.0.0.
'spinner' 1.0.0..<2.0.0 practically depends on 'rainbow' 3.0.0..<4.0.0 because 'spinner' 1.4.0 depends on 'rainbow' 3.0.0..<4.0.0 and 'spinner' 1.4.1 depends on 'rainbow' 3.0.0..<4.0.0.
'spinner' {1.0.0..<1.4.0, 1.4.2..<2.0.0} practically depends on 'rainbow' 3.0.0..<4.0.0 because 'spinner' 1.3.1 depends on 'rainbow' 3.0.0..<4.0.0 and 'spinner' 1.3.2 depends on 'rainbow' 3.0.0..<4.0.0.
'spinner' {1.0.0..<1.3.1, 1.3.3..<1.4.0, 1.4.2..<2.0.0} practically depends on 'rainbow' 3.0.0..<4.0.0 because 'spinner' 1.2.1 depends on 'rainbow' 3.0.0..<4.0.0 and 'spinner' 1.3.0 depends on 'rainbow' 3.0.0..<4.0.0.
'spinner' {1.0.0..<1.2.1, 1.2.2..<1.3.0, 1.3.3..<1.4.0, 1.4.2..<2.0.0} practically depends on 'rainbow' 3.0.0..<4.0.0 because 'spinner' 1.1.6 depends on 'rainbow' 3.0.0..<4.0.0 and 'spinner' 1.2.0 depends on 'rainbow' 3.0.0..<4.0.0.
'spinner' {1.0.0..<1.1.6, 1.1.7..<1.2.0, 1.2.2..<1.3.0, 1.3.3..<1.4.0, 1.4.2..<2.0.0} practically depends on 'rainbow' 3.0.0..<4.0.0 because 'spinner' 1.1.4 depends on 'rainbow' 3.0.0..<4.0.0 and 'spinner' 1.1.5 depends on 'rainbow' 3.0.0..<4.0.0.
'spinner' {1.0.0..<1.1.4, 1.1.7..<1.2.0, 1.2.2..<1.3.0, 1.3.3..<1.4.0, 1.4.2..<2.0.0} practically depends on 'rainbow' 3.0.0..<4.0.0 because 'spinner' 1.1.2 depends on 'rainbow' 3.0.0..<4.0.0 and 'spinner' 1.1.3 depends on 'rainbow' 3.0.0..<4.0.0.
'spinner' {1.0.0..<1.1.2, 1.1.7..<1.2.0, 1.2.2..<1.3.0, 1.3.3..<1.4.0, 1.4.2..<2.0.0} practically depends on 'rainbow' 3.0.0..<4.0.0 because 'spinner' 1.1.0 depends on 'rainbow' 3.0.0..<4.0.0 and 'spinner' 1.1.1 depends on 'rainbow' 3.0.0..<4.0.0.
'spinner' {1.0.0..<1.1.0, 1.1.7..<1.2.0, 1.2.2..<1.3.0, 1.3.3..<1.4.0, 1.4.2..<2.0.0} practically depends on 'rainbow' 3.0.0..<4.0.0 because 'spinner' 1.0.5 depends on 'rainbow' 3.0.0..<4.0.0 and 'spinner' 1.0.6 depends on 'rainbow' 3.0.0..<4.0.0.
'spinner' {1.0.0..<1.0.5, 1.0.7..<1.1.0, 1.1.7..<1.2.0, 1.2.2..<1.3.0, 1.3.3..<1.4.0, 1.4.2..<2.0.0} practically depends on 'rainbow' 3.0.0..<4.0.0 because 'spinner' 1.0.3 depends on 'rainbow' 3.0.0..<4.0.0 and 'spinner' 1.0.4 depends on 'rainbow' 3.0.0..<4.0.0.
'spinner' {1.0.0..<1.0.3, 1.0.7..<1.1.0, 1.1.7..<1.2.0, 1.2.2..<1.3.0, 1.3.3..<1.4.0, 1.4.2..<2.0.0} practically depends on 'rainbow' 3.0.0..<4.0.0 because 'spinner' 1.0.1 depends on 'rainbow' 3.0.0..<4.0.0 and 'spinner' 1.0.2 depends on 'rainbow' 3.0.0..<4.0.0.
'spinner' {1.0.0..<1.0.1, 1.0.7..<1.1.0, 1.1.7..<1.2.0, 1.2.2..<1.3.0, 1.3.3..<1.4.0, 1.4.2..<2.0.0} practically depends on 'rainbow' 3.0.0..<4.0.0 because 'spinner' 1.0.0 depends on 'rainbow' 3.0.0..<4.0.0.
'spinner' {1.0.0, 1.0.7..<1.1.0, 1.1.7..<1.2.0, 1.2.2..<1.3.0, 1.3.3..<1.4.0, 1.4.2..<2.0.0} practically depends on 'rainbow' 3.0.0..<4.0.0 because no versions of 'spinner' match the requirement {1.0.7..<1.1.0, 1.1.7..<1.2.0, 1.2.2..<1.3.0, 1.3.3..<1.4.0, 1.4.2..<2.0.0} and 'spinner' 1.0.0 depends on 'rainbow' 3.0.0..<4.0.0.

So I'm using a newer version of Rainbow but Spinner depends on an older version. So I just remove my Rainbow dependency and problem solve.

What if I want to use the latest version of Rainbow? Can I make the Spinner use my newer Rainbow?

You could try forking Spinner, update its Package manifest to use Rainbow 4+ , depend on your fork, instead of the original one and see what breaks...

If nothing breaks you could submit that change to the Spinner project as a PR.

3 Likes

Do you mind filing an issue against SPM for improved error formatting when dependencies fail to resolve? cc @Max_Desiatov who might be interested

1 Like
2 Likes

I forked spinner, and change the Rainbow package version. But when I switch to mine fork/patch Spinner, I get:

error: Dependencies could not be resolved because no versions of 'spinner' match the requirement 1.0.0..<2.0.0 and root

Edit: so I have to add a tag to my git.