Dependency management #7
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
There should be two types of dependencies:
dependencieskey.dev_dependencieskey. This includes things like build dependencies and test dependencies.Running
nc add <dep>will add it todev_dependenciesby default, but if the package is used in some way such that any users of the library will require it, it will automatically be moved todependencies.This way, users of a library will have the minimum number of dependencies, while also creating minimal hassle for library maintainers, as
nc.tomleffectively manages itself.Would the plan be to have like mod.nclang.org, or go the more golang route and do .git repos being the module root, and access see it to a global module root, so something like
github.com/codycody31/nc-nano64->nano64/nano64|nano64/utils, etc?This issue is actually out of date on how dependency management will work, I'll write up an updated version later. It'll be based on Git repos, but closer to Rust than Go. The dependency file will look like:
I'm thinking the module root's
lib.ncfile can be the entrypoint to the library. Soimport "some-dep" as somedepwill importcodeberg.org/user/some-dep@commit/path/to/module/root/lib.nc.The command line way of adding dependencies will be:
The lockfile can then store all the same data, but also a checksum to validate against:
You, as the consumer of the dependency, get the control over what you name the dependency in your code. So for example, you can have two different packages named "some-pkg" without causing naming conflicts, simply by giving them different names in your
nc.toml.Also there are no pre/post-install scripts, nor are there transitive dependencies. If a package you need has dependencies of its own, it needs to declare that in the project README or somewhere. Hopefully that should generally keep the dependency counts low, and avoid the nonsense that tends to happen in NPM, Cargo, Pip, etc. It'll also let you pick and choose the subdependencies you need depending on the parts of the library you actually use. For instance, if you're using an image processing library, but you only need to convert between JPEG and PNG, then there's no reason for you to import subdependencies for all the other image formats.
There's a few more details to work out, and probably a few things that I'm missing too, but that's where I'm at right now. Also TOML isn't a fixed decision for the file format, maybe KDL or something might be better to have a more XML-like structured representation of the dependency tree, which would allow having multiple versions of dependencies and scoping subdependencies to their parents, etc.
Edit: We might also be able to get away without having a separate lockfile, and just having all the config in one file, if we move the checksum to the main config file.
mmm, seems good except for lib.nc, is this not a magic feature? I'd prefer like
import("somedep/somedep")since it aligns better. Also, I think we need the spec defined for modules on how to import and then export, ie: if we do a lib.nc, it needs to import submodules and provide access, properly, maybe likesomedep.crypto.entropy(), making it use dots to access? since we need a scope management or something, as making everything sit undersomedep.cryptoEntropy()etc, or other routes doesn't make sense.Furthermore, not taking in deps of a dep makes things really hard, since the idea is that the parent marks it as a dep, while the dep itself cannot, which makes using multiple versions of something a bit of a pain, also how would this affect if we import a dep under a different name, but a dep that uses that has it under a different one?
These are all good points. Honestly, I might end up reworking the module system entirely eventually, but I want to look a bit more into how other languages do it, and adapt it from there. The current system is very JavaScript-esque, but I'm actually interested in how Zig does modules, and if we can adapt something from that. I imagine the best system lies somewhere in the middle of everything else.
For now, you can implement the design as written on https://nclang.org/syntax/modules (or just ignore it since you shouldn't need to import dependencies outside the stdlib, especially since none exist), but keep in mind that the syntax and system for importing modules may change.
For names: you're right that it wouldn't work. Maybe the config file should have a
namefield that anyone who imports that library must use.As for subdeps of deps, I'm not disallowing that, I'm just adding some friction to choosing libraries with tons of transitive dependencies. You'd still be able to have subdeps of deps, with subdep versions scoped to each dep, you'd just have to declare the tree structure manually:
That's why I wanted to use KDL, it makes declaring both properties and children really straightforward, compared to something more object-oriented like JSON/YAML/TOML. XML would also work for this, since it's also a document language, but KDL looks more minimal.
The idea is that if you have to declare your entire tree of dependencies manually, or at least see it in your main config file, then you become far more aware of what you're pulling in, than if it gets hidden inside a lockfile you never bother to open. That, combined with a large stdlib, should hopefully discourage large numbers of dependencies for most things.
import "nano64"is actually lib.nc