How can I make `import Numerics` work in every project automatically?

Some packages are “preinstalled”, such that they do not need to be listed in Package.swift and can simply be imported without any ceremony. For example, I can write import Foundation or import Dispatch and it “just works”. It even works in the Swift REPL from the command line.

I write a lot of numerical code, and I often import the Swift Numerics package. It is tedious to configure every single program I make just to let me import that package. I want to be able to write import Numerics in any Swift file in any Swift project anywhere on my computer, and have it just work.

How can I tell the compiler “Hey, the package Numerics is located at the following path, please use that anywhere you see import Numerics (unless otherwise specified in a Package.swift file)”?

In other words, how can I “install” the Swift Numerics package so that import Numerics “just works”?

This won't work for all the hosts, but at least on Windows, you should be able to accomplish this by shipping a custom SDK with the Numerics module pre-installed.

If you use Windows and don't mind trying a paid product, then Plain Swift can do exactly that: "install" a Swift module once and import it in any project later on.

I am not on Windows, I do not want to make a purchase, and I do not want to build a custom SDK. I simply want to tell the Swift compiler where to find certain libraries, so they can be imported in my projects without any extra ceremony.

This seems like it should be a super common thing. “Oh, this package looks useful, I think I’ll download and install it so I can start using it.” That is, like, the most basic and convenient workflow.

So… is it possible? If so, how?

Obviously any project that actually gets shipped and published will need a proper Package.swift file that specifies its dependencies. But the vast majority of things I code are for my own personal use, many of them have the same few dependencies over and over, and the process of prototyping would be much nicer if I could skip the repetitive boilerplate of wrangling those common dependencies every time.

Yeah, it ought to be possible to do this by installing the module into one of the default module search paths on your system. Someone who's more into the details of such things can probably provide immediate guidance, but otherwise I'll play around with it sometime in the future and get back to you.

What not-Windows OS are you using?

1 Like

No, wait, hang on. “I want to install this library for everyone on the system” is definitely a model everybody is moving away from. Rust’s Cargo doesn’t support this, NPM discourages it, Python and Ruby are encouraging venvs over a single global source of truth, even Apple wants you to target an SDK rather than “whatever’s in /“. (I wish I knew more about Go to state something definitively there too, but certainly the few Go projects I’ve worked with have all their dependencies listed explicitly in files.)

I get that there’s a convenience use case for this, and that we don’t have something like venvs for SwiftPM yet, but let’s not jump to saying the “default system include path” is a good thing.

5 Likes

Another big problem with the idea of installed modules is that the .swiftmodule files emitted by the compiler are version-locked to the toolchain. So imagine you had /some/search/path/Numerics.swiftmodule being used by default everywhere, built with toolchain version 6.0. Once Swift 6.1 came out, you'd have to rebuild all of those modules again with the new toolchain, or maintain differently versioned copies of them (and make sure that each toolchain had the right versions on its search path).

(The modules are also dependent on other build settings like the target platform—a .swiftmodule built for macOS won't work if you wanted to target iOS—but I'm gathering from the request here that you're looking for something to use for host tools/scripts, where you just target the platform you're on.)

If those modules supported library evolution, you could use .swiftinterface files instead of .swiftmodule files and the compiler would compile them on demand for you in the implicit module cache (stored someone amongst your temp directories), but if a module you wanted to use didn't support library evolution, that wouldn't be an option.

3 Likes

MacOS, currently 14.6.

I’m the only user of my machine, so I’d be fine with just making it work for my own user account.

I don’t know the details of how the compiler works, but when I make a project and add SwiftNumerics to its Package.swift file (let’s say, pointing at a filepath on my local system) the compiler does something when I compile that project.

For my purposes, I don’t really care whether Numerics gets pre-compiled once, or if it just gets “auto-included as necessary” in any project that imports it. I’m just trying to avoid the boilerplate in every single little program that I write whenever I want to do something mathy.

One of the Xcode betas (from last year?—timelines are fuzzy now) shipped with this feature exactly: you type import Numerics and everything would be automagically added to the project. There were...problems and Xcode doesn't do that anymore.

I'm not saying it's "a good thing", but that's not a reason why it should be impossible.