Replies: 5 comments 7 replies
-
If I understand correctly, a problem with the nimble lock-files solution is that (almost?) none of Status' repositories are properly tagged. In this case, I propose we could lead by example and properly tag the repositories under our control. Correct me if I'm wrong, but tagging them won't interfere with the Nimbus build system method we're using right now. If nimble lock-files is the supported solution and will be in the future, then I propose we use it. However, I wouldn't suggest we decide to migrate right now for two reasons: I'd like to know all about those previously mentioned set of issues. And I'd like someone much more experienced with nim/nimble and the nimbus build system to do perhaps a time-boxed trial run. |
Beta Was this translation helpful? Give feedback.
-
After today's meeting we seemed to reach a consensus that we can do both Nimble lock files and the Nimbus build system. It's a bit more work, but along with begging to tag releases will get us better positioned to use semantic versioning with Nimble files in the future. Initially it seems we'd want use the Nimbus build system for CI, but ensure that the Nimble file and Nimble lock files are consistent with the vendored versions. I have a small utility that can sync them pretty easily. |
Beta Was this translation helpful? Give feedback.
-
Updated Thoughts!Note that yesterday I ended up changing my thinking a bit. Originally I was thinking mainly about Nimble lockfiles. Looking more at the Nimbus build system with We can still use Nimble lock files, however, likely with a utility to generate Nimble lock files from the Nimbus build system. Doing this more for tagging deps and getting habits ready for SemVer. Generally I think Atlas matches the Nimbus build system setup more naturally, but it's not yet ready as a full replacement. Skip to the last section for thoughts on using Atlas and Nimbus together. It's likely a matter of months before Atlas could be feature compatible with Nimbus build system and potentially fully replace Nimbus. BackgroundNimbleNimble 0.14.* have been sorta of a pain, but lock files do work. However they don't work all to well with the old The new nimble 0.14 workflow is more complicated due to how it verifies hashes on dependencies. It's a great idea! Unfortunately the implementation details and ecosystem present challenges when working with multiple deps. I still don't understand how to use Nimble 0.14 with a workspace style setup ( ^_^" ). Nimble 0.14 works on a Nimble directory structure looks like (Nimble 0.13 used
It's important to note that the folders in the Nimble Now in Nimble 0.13 you could setup a global develop link so you could create a sort of workspace:
Nimble 0.14 also verifies each dependency every time you build or run tests, which leads to difficulties when working on "dirty deps". The ability to work on these may have been added, but it's been somewhat fragile. I've backed out of using Nimble 0.14 in my Nim projects at least twice. Pros of Nimble 0.14 are lockfiles and the ability to replicate builds much better. Especially with the lack of proper tagging on many Nim deps. However, the lockfiles must include both the Git commit hash and another hash of the project to work. For developing single packages Nimble 0.14 works well! But it fails when working with workspaces of related dependencies. NimbusWith Nimbus build system we get a setup much more like a workspace:
Where This works well for CI and reasonably well for working with multiple projects. You can go into the Unfortunately, to build dependencies and such the Nimbus build system actually shims the Nimbus also uses a AtlasAtlas seems to have been designed starting with some of the best points of the Nimbus build system. It's designed around workspaces first and all dependencies are cloned repos. Atlas main style workspace looks like:
Note that the You use Atlas by going into the project directory That means you can use regular So far pretty simple. It can get a bit confusing as you need to remember that in this setup all projects share the same dependencies, which has pros and cons. However, note that version resolution is pretty broken in Atlas still! It's being worked on, but essentially it currently will work like Nimble 0.13 and use the master/main branches. Shared dependency versions in AtlasNow if you go into another project A pro of this setup is that now you can go back to However, for a project like Codex with one master project, it's nice since you don't really need to worry about ensuring You can also switch quickly between versions since they're all Git repos by running Open problems remain for how Atlas can handle generated binary libraries when switching between dependency versions. Likely a "brute force" could suffice which would rebuild any libraries when the version is changed. This would be somewhat similar to changing deps with Nimbus build system. Atlas Lock FilesAtlas supports lock files as well. So you can also do: cd codex_ws/projectFoo/
atlas lock atlas.lock
atlas replay atlas.lock To set this project back to it's deps. Running Integrating Nimbus Build System with AtlasI noted that Nimbus build system and Atlas were more compatible in the first paragraph, but so far they seem fairly different. However, I recently added a PR to Atlas to add support for "inverted workspaces". In this mode you can setup Atlas workspace to look like:
Basically Atlas can work with a Nimbus vendor folder! In this case With this setup you can run Another useful command is These features be useable with Nimbus vendor folder after my PR gets in. I've already been using Atlas in combination with Nimbus build system already. Once Atlas dependency resolution is working it'll let us have the benefits of using SemVer with the Nimbus build system. Based on this it seems to me that Atlas will provide a much more natural upgrade from the Nimbus build system. It's possible Nimbus build could just integrate Atlas so as to retain the same workflows but simplify it's setup and usage. |
Beta Was this translation helpful? Give feedback.
-
Fantastic writeup, Thanks! In my view part of the problem comes from naturally conflicting requirements:
Reproducible builds:
Dependency resolution is instead about specifying a version range for dependant libraries.
In my understanding, dependency resolution tries to find a single version for each library that matches all the range requirements, but of course these ranges (and dependencies) themselves depend on the choices made, so it is quite a problem. I'm not sure how well defined and deterministic algorithms are in this regard. From what I see in various systems that I use (apt, pip, nimble), this is not well understood. To these two, we can add the requirement for:
NBS is conceptually not bad, but if you look at the Makefiles, there are some scary things in there. Also it is not meant to handle dependency ranges. In general, I think the community would need much more automated tools for handling the relation between the requirement for reproducible builds and dependency resolution. |
Beta Was this translation helpful? Give feedback.
-
@elcritch, I can tell from your write-up that you are likely not familiar with the intended way to setup "workspaces" in the new Nimble. Admittedly, the documentation for this is not quite adequate, but I can explain the details in a quick call. The following Nim forum post is a good introduction, as well as the documentation for the https://github.com/status-im/nim-workspace#sync-vendor-revisions-to-workspace So let's have a discussion that will make sure you are making a fully informed decision here. |
Beta Was this translation helpful? Give feedback.
-
Dependencies versioning issues
Nimble issues summary
Nimble pre lock files (< 0.14.2)
Nimble install policy is as follows:
Versions
Versions of cloned packages via Git or Mercurial are determined through the
repository's tags.
When installing a package which needs to be downloaded, after the download is
complete and if the package is distributed through a VCS, Nimble will check the
cloned repository's tags list. If no tags exist, Nimble will simply install the
HEAD (or tip in Mercurial) of the repository. If tags exist, Nimble will attempt
to look for tags which resemble versions (e.g. v0.1) and will then find the
latest version out of the available tags, once it does so it will install the
package after checking out the latest version.
You can force the installation of the HEAD of the repository by specifying
#head
after the package name in your dependency list.However, due to several issues with nimble itself, which invalidated versioning, tagging has been neglected across many packages, this is the case with most status nim packages. This breaks any sort of semantic versioning.
Nimble with lock files (>= 0.14.2)
nimble lock
The
nimble lock
command will generate or update a package lock file namednimble.lock
. This file is used for pinning the exact versions of thedependencies of the package. The file is intended to be committed and used by
other developers to ensure that exactly the same version of the dependencies is
used by all developers.
Currently the lock file have the structure as in the following example:
version
- JSON schema version.packages
- JSON object containing JSON objects for all dependencies,chronos
- Nested JSON object keys are the names of the dependenciespackages.
version
- The version of the dependency.vcsRevision
- The revision at which the dependency is locked.url
- The URL of the repository of the package.downloadMethod
-git
orhg
according to the type of the repository aturl
.dependencies
- The direct dependencies of the package. Used for writing thereverse dependencies of the package in the
nimbledata.json
file. Thosepackages' names also must be in the lock file.
checksums
- A JSON compound object containing different checksums used forverifying that a downloaded package is exactly the same as the pinned in the
lock file package. Currently, only
sha1
checksums are supportedsha1
- The sha1 checksum of the package files.If a lock file
nimble.lock
exists, then on performing all Nimble commandswhich require searching for dependencies and downloading them in the case they
are missing (like
build
,install
,develop
), it is read and its content isused to download the same version of the project dependencies by using the URL,
download method and VCS revision written in it. The checksum of the downloaded
package is compared against the one written in the lock file. In the case the
two checksums are not equal then it will be printed error message and the
operation will be aborted. Reverse dependencies are added for installed locked
dependencies just like for any other package being locally installed.
Potential solutions
Beta Was this translation helpful? Give feedback.
All reactions