c3lang / c3c

Compiler for the C3 language
GNU Lesser General Public License v3.0
1.35k stars 80 forks source link

Module versioning #821

Open lerno opened 1 year ago

lerno commented 1 year ago

Consider some versioning scheme for various elements in the build/manifests:

Possible design:

  1. Dependency contains no-version, major version, minor version, major + minor + build or list of major versions
  2. Try to resolve the major version to use. If none is selected, pick max. More than one are required -> compile error (example: A needs 1, 2, B needs 2, 3 => pick 2, A needs 1, 2, B needs 3, 4 => error)
  3. Pick the maximum minor + build version available. If this is less than minimum minor + build version needed => error.
  4. Excluding versions should be possible, eg exclude 1.3.4
lerno commented 1 year ago

Go Modules work like this:

  1. Build file contains required library versions: e.g. 2.5.7
  2. First number is major version number and is considered incompatible (basically a different module completely)
  3. Dependency resolution per major library version is done by picking the minimal version. E.g. module Foo requires Bar 1.5+ and module Baz requires 1.3+. Our module using Bar and Baz will resolve the minimal version to 1.5. This is the version that will be used. Note that if Foo used 2.5+, then both Bar 2.5 and 1.3 would be required.
pierrec commented 1 year ago
3. Dependency resolution per major library version is done by picking the minimal version. E.g. module Foo requires Bar 1.5+ and module Baz requires 1.3+. Our module using Bar and Baz will resolve the minimal version to 1.5. This is the version that will be used. Note that if Foo used 2.5+, then both Bar 2.5 and 1.3 would be required.

You mean Bar and Baz resolve to 1.3 right?

How would the version be specified? only in the project or other manifest file or in the module path as is the case in Go?

lerno commented 1 year ago

No, they resolve to 1.5 since Bar needs 1.5+. Different major versions are considered distinct libraries.

lerno commented 1 year ago

Module would be defined in manifest.json / project.json. A simple scheme is saying -lib foolib grabs any foolib -lib foolib@1.5 means foolib 1.5+ etc:

Ideally look up if there is some standardized way to do the above.

lerno commented 1 year ago

Things like this should be considered: https://www.lucidchart.com/techblog/2017/03/15/package-management-stop-using-version-ranges/

pierrec commented 1 year ago

Maybe also have a look at what Zig si doing. They have introduced their package manager recently (I havent looked at it yet).

lerno commented 1 year ago

I am not really looking at a package manager. I think downloading dependencies using other means is fine. Because of how C3 libraries work (essentially zip files with some metadata) they're easy to just drop manually into any project - no package manager needed. The only thing that's necessary is to determine how to select a package if you have dropped two libraries of the same type into your dependencies. Basically "what does that mean" when you then want to include a library.

Because we're not doing package dependency resolution for pulling in packages, we're essentially only about selection.

So say that you have your code, and then you drop in foolib@1.5.1 foolib@1.5.0 foolib@2.3.0?

So for example it could work like this:

  1. You just write --lib foolib => use the latest, 2.3.0
  2. You write --lib foolib@1 => use the latest 1.x => 1.5.1
  3. You write --lib foolib@1.5.0 => use 1.5.0
  4. You write --lib foolib --lib barlib and barlib depends on 1.5.0+ => Use 1.5.0 (MVS)
  5. You write --lib foolib@2 --lib barlib => error (or link both??)
  6. You write --lib foolib@1 --lib barlib => Use 1.5.0 (MVS)
pierrec commented 1 year ago

I like this actually. Package managers are a nightmare. Thanks for the explanations.