How to use SPM?

Let's say I initialised a package by typing this swift package init --type=empty. Then I have nothing but a basic default folder structure. Then I want to add a new file to Sources and set it in the manifest to be treated like an executable. How should it be done?

You can run swift package init --type=executable to see what a minimal executable package looks like.

1 Like

I dont need to default it to executable. I want a fresh project without anything set up for me so I can figure out how to use the thing. I want to know how to add files when I need to do it.


I started with an empty package that looked like this
Screen Shot 2021-11-17 at 05.40.08
Then I want to add a file like so
Screen Shot 2021-11-17 at 05.41.46
But when I specify in manifest what I want to stuff in the package like this

let package = Package(
    name: "pondering",
    products: [
      .executable(name: "exec", targets: ["exe"])
    ],
    targets: [
      .executableTarget(name: "exe", path: "/Sources/Test")
    ]
)

I get this error error: target path '/Sources/Test' is not supported; it should be relative to package root
The question is 'how can I do it?'
Do you suggest that I should make a new package every time I want a new executable?

I think Steven is suggesting you look at the structure that gets created with --type=executable and use that as a reference for your own work.

I get this error error: target path '/Sources/Test' is not supported; it should be relative to package root

Your path is absolute. It needs to be relative:

.executableTarget(name: "exe", path: "Sources/Test")
1 Like

Doesn't work. Now I get error: invalid custom path 'Sources/Test' for target 'exe'

NVMD. It works, thank you for reply

Or so I thought...
After spending a little more time I got stuck again.


Now my project has this structure
Screen Shot 2021-11-17 at 07.04.02
And manifest is this

let package = Package(
    name: "pack",
    products: [
      .executable(name: "exec", targets: ["exe"])
    ],
    targets: [
      .target(name: "AGroup", path: "Sources/A"),
      .target(name: "BGroup", path: "Sources/B"),
      .target(name: "Combo", dependencies: ["AGroup"], sources: [
         "Sources/B/funk.swift"
      ]),
      .executableTarget(name: "exe", dependencies: [
         .target(name: "AGroup"),
         .target(name: "BGroup")
      ]),
    ]
)

And I get error: Source files for target Combo should be located under 'Sources/Combo', or a custom sources path can be set with the 'path' property in Package.swift

I don't understand why I cannot define logical blocks and need to reflect everything in a project structure. My understanding was that everything inside Sources are merely folders to which no special meaning is attached. Apparently, it is not so and this seems wicked.

Is it the case that spm does not allow to define logical modules?

The default “path” for a target is “Sources/(target.name)” so if you do not specify one it will use that.

Second the “sources” is relative to the path, so your “Combo” target will try to get the source from “Sources/Combo/Sources/B/funk.swift”

Third, currently SPM does not allow for overlapping. So if your BGroup target already contains B/funk.swift, it can’t be in the Combo target.
If you really want it to be Combo target not on BGroup, you should exclude it from BGroup target.

And all the above is available on GitHub - apple/swift-package-manager: The Package Manager for the Swift Programming Language
If you have any question, the source is your friend. :)

More specially, you can check the source file here swift-package-manager/Target.swift at 9e0124e1f3895ad14025806a0046951d3abf634b · apple/swift-package-manager · GitHub

I managed to pass the stage with spm, but now – with config and import statements in place –
xcode keeps popping me errors about how it does not recognise the imported module, although when I type ModuleName. autocomplete show that it sees everything that should be in the module. :pensive:

After a quick skimming on the net, I tried everything that was offered there as a potential solution, but haven't managed to resolve my problem and got more ascertained that this is a bug in spm implementation.

Why doesn't it just let me write anything? :tired_face:


Screen Shot 2021-11-18 at 06.19.18

let package = Package(
    name: "casper-pragma",
    products: [
      .executable(name: "Knot", targets: ["KnotExe"])
    ],
    targets: [
      .target(name: "Sigil", path: "Sources/Sigil"),
      .executableTarget(name: "KnotExe", dependencies: [
         .target(name: "Sigil"),
      ], path: "Sources/Knot")
    ]
)

Do you see if anything here causes trouble on my part?

The issue was on me. I didn't add visibility markers. :woozy_face:
And you know what? I am getting no more errors! From spm...

As if it was not enough sentence for me already, now when I run tests, spm reports that is has performed zero of them. I have no fucking idea why. :no_mouth: :gun:

Try to provide more information than this. There's no way anyone can help you with this little information. Show me the full package.swift file, which should include declarations of the test targets, and all the source files for the tests. Alternatively, publish the package to github and post a link.

1 Like

This was because names of methods for testing that I defined in XCTestCase was not prefixed with 'test'. I can't find words to express how bulshit this is...

You should've read the documentation. It's not hard to find.

Terms of Service

Privacy Policy

Cookie Policy