Following is the RFC for providing project local dependencies in Nimble. This is being tracked in issue 131 and discussed in the Nim forum.
Definitions:
local deps mode
- this RFC to enable project local dependencies where$prj/nimbledeps
is used by Nimble on a per project basisuser deps mode
- current Nimble behavior of using~/.nimble
since dependencies are usable across projects for a specific userglobal deps mode
- tracked in issue 80 where a system-wide folder can be used to store dependencies across users and projects. It is not covered in this RFC.
Motivations:
- The main value of
local deps mode
is to provide dependency isolation from other projects. Isolation simply makes development easier and avoids any conflicts caused by mixing dependencies across projects. local deps mode
is simply a mode of operation during development and is not expected to be checked into source control. The intention is not to push vendoring or an alternative for lock files. It is not aimed at solving any distribution related challenges or enabling reproducible builds.- If a user wants
local deps mode
for a particular project, it implies they want complete isolation. As a result, Nimble will no longer consideruser
orglobal
dependencies and commands will all act as if$prj/nimbledeps
is the only directory Nimble uses. - Once a working configuration is reached regardless of
deps mode
, the user could then generate a lock file that improves on distribution. That design will be discussed separately and not distract this RFC. - This RFC mainly describes Nimble behavior at this time. The changes required for Nim to understand
local deps mode
will be addressed later.
All behaviors below that drive actual code changes are highlighted with *
.
Behavior:
- All nimble commands will highlight when in
local deps mode
so that it is amply clear to the user*
- An explicit
--nimbleDir:xxx
overrideslocal deps mode
. - If
$prj/nimbledeps
directory exists, setlocal deps mode
by forcingnimbleDir = $prj/nimbledeps
*
- Else, continue in default
user deps mode
Command-line behavior in local deps mode
:
nimble install
- Install all the project's dependencies into
$prj/nimbledeps
- Build binaries if applicable
- Do not copy the project itself into
$prj/nimbledeps
- inform user*
- Install all the project's dependencies into
nimble install -d | --depsOnly
- install all the project's dependencies into$prj/nimbledeps
nimble install url|pkg
- install dependency into$prj/nimbledeps
nimble uninstall pkg
- remove pkg from$prj/nimbledeps
nimble uninstall pkg -i
- remove pkg and packages that depend on it from$prj/nimbledeps
nimble build
- install deps into$prj/nimbledeps
in the processDeps stepnimble develop
- Install all deps into
$prj/nimbledeps
in the processDeps step - Do not create any links to itself it in
$prj/nimbledeps
- inform user*
- Install all deps into
nimble develop prj2
- Clone
prj2
into sub-directory withinprj1
and add a link into$prj/nimbledeps
- Clone
nimble develop prj2 --nimbleDir:$prj1/nimbledeps
- Clone
prj2
into directory outsideprj1
and link into$prj1/nimbledeps
- Clone
- To use an existing project
$prj2
as a dependency inlocal deps mode
project$prj1
:cd $prj2
nimble develop --nimbleDir:$prj1/nimbledeps
local deps mode
is a mode of operation during development and not for influencing distribution. While it is not recommended, users can save local deps mode
in source control by:
- Checking in
$prj/nimbledeps/empty.txt
- Checking in
$prj/nimbledeps/*
- vendoring or poor man's lock files - Need to verify that
nimble install
of such a project does not break - Nimble should not get confused what the truenimbleDir
is when processing such deps
No changes:
- All commands will continue to run like they do today when in
user deps mode
- Dependencies will need to be added to the
.nimble
file in therequires
section per usual to get installed from scratch regardless ofdeps mode
Caveats:
- Checking in
$prj/nimbledeps/*
into source control will work as expected for the project when checked back out but if the project is itself installed by a parent project, these checked-in deps should not be inherited. The dependencies will get pulled from~/.nimble
or$prj/nimbledeps
of that parent project depending on its configuration. This is similar to how lock files work for libraries. - If a project with local deps has a dep which builds binaries, it will install into
$prj/nimbledeps
which means the binaries will not be in~/.nimble/bin
, typically in$PATH
. User is expected to add$prj/nimbledeps/bin
to the$PATH
.
Replies to some of the comments here.
This is being addressed in two ways - one is for nimble to be vocal about local deps mode in every command so that user knows where deps are being installed and coming from.
Second, local deps is opt in - you need to do something for it to be in effect. If you checkout someone else's project that uses local deps, nimble will remind you as noted above.
nimble uninstall
of a package that other packages depend on fails altogether and displays the list. You need to use-i
to force remove it and all the others too.As I have noted above,
nimble install
andnimble develop
can be made to behave in a variety of ways depending on this change. Some of them are not compatible with~/.nimble
at all which means a project with local deps cannot then be used by other global projects on the system. This is highlighted by @disruptek's last comment. Maybe that's okay but it isn't obvious. We need a clear definition of how things change with this feature.Whatever it is, it needs to be obvious and consistent. If you want to install or link (develop) in
~/.nimble
then deps also need to be installed in~/.nimble
. It could mean that these commands do both project local and~/.nimble
management simultaneously but seems wasteful and confusing. Maybe there should be a flag to force~/.nimble
when local deps are in effect. Perhaps a--user
or something. This seems more sensible since it will be a less frequently used and could do fine with requiring the user to be deliberate.I don't want to mix up
--global
in this proposal cause there's a different issue for that.