Search code examples
juliadependency-managementvirtual-environment

Environments inherit packages from default environment


Note: This question refers to Julia v1.5. Of course, at any time the answers should ideally also answer the question for the most recent version.

A Julia installation provides a default environment (called, e.g., @v1.5). When running Julia in a certain working directory, one uses julia>] activate . to either make a new environment or activate the present environment (in case the current folder contains files such as Project.toml).

When Julia code is running in a certain environment, the environment defines what packages (or modules) can be imported via using or import. However, packages installed in the default environment can always be used. I haven't seen this fact mentioned in the docs (although it likely is mentioned) and learned this "the hard way" after spending some time tracking down missing imports.

This has upsides and downsides: sometimes one feels the need to use packages that are not really part of the project, e.g., for profiling or debugging. If these are installed in the default environment, one can use them without polluting project dependencies. On the other hand, it could happen that one forgets to add a certain package to the environment of a project although the project uses the package. In that case other users cannot reproduce the necessary environment from just Project.toml and Manifest.toml. (Adding non-trivial code to the Julia script that gets run on Julia startup can also have this downside).

The way I see it, one has several ways of dealing with this issue:

  1. Use packages inherited from the default environment (and scripting on Julia startup) at will and have CI with extensive unit tests for reproducibility
  2. Never add packages to the default environment. Take care not to import packages in scripting on Julia startup.
  3. Just include all packages you want in Project/Manifest files, regardless of whether the actual repository code uses them.

My questions: Are there more (better?) ways to deal with this problem? Which choice is idiomatic for Julia?


Solution

  • LOAD_PATH is responsible for determining which environments compose to form the effective environment. By default, it includes the active environment, the default environment, and stdlibs.

    Tests, when activated by Pkg.test (or equivalently pkg> test) are run with a sterile load path consisting of only the project being tested. So tests will only have access to the dependency graph defined by the respective Project.toml and Manifest.toml files.

    It seems to be standard practice to include utilities (e.g. profiling tools) in your default environment.

    If you do not like this behavior, you can modify LOAD_PATH in your startup file to only include the active project.