How do I stop pkg> up from breaking my ControlSystems environment?

Hi, I’m quite new to Julia.

I’m using ControlSystems a lot but I have several issues with it.

In particular, when I’m doing ] up (I’m generally doing it for other reasons not related to ControlSystems), ControlSystems and its dependencies update as well and it is always breaking my Julia environment. It has already happened 2 different times this last month.

Please tell me what I’m doing wrong and how should I fix my workflow. It takes me hours upon hours to fix these issues, which I think can be easily avoided through compatibility and versioning.

thanks

Hi!

Unfortunately, you didn’t elaborate what exactly breaks in your environment, so I can’t help you with that. But you always can pin the version of ControlSystems by running ] pin ControlSystems@x.y.z to prevent updating this package (where x.y.z is the version that works for you)

1 Like

Sorry. so the up gave me this (related to ControlSystems dependencies)

  [2b5f629d] ↑ DiffEqBase v6.183.2 ⇒ v6.189.1
⌃ [f6369f11] ↓ ForwardDiff v1.1.0 ⇒ v0.10.38
  [7ed4a6bd] ↑ LinearSolve v3.28.0 ⇒ v3.40.0
  [1dea7af3] ↑ OrdinaryDiffEq v6.101.0 ⇒ v6.102.1
  [bbf590c4] ↑ OrdinaryDiffEqCore v1.30.0 ⇒ v1.34.0
  [4302a76b] ↑ OrdinaryDiffEqDifferentiation v1.14.0 ⇒ v1.16.0
  [becaefa8] ↑ OrdinaryDiffEqExtrapolation v1.8.0 ⇒ v1.9.0
  [b0944070] ↑ OrdinaryDiffEqLowStorageRK v1.6.0 ⇒ v1.7.0
  [43230ef6] ↑ OrdinaryDiffEqRosenbrock v1.16.1 ⇒ v1.17.0
  [669c94d9] ↑ OrdinaryDiffEqSSPRK v1.6.0 ⇒ v1.7.0

and the error that resulted is this:

WARNING: could not import OrdinaryDiffEq.DiffEqBase into ControlSystems
ERROR: LoadError: UndefVarError: `DiffEqBase` not defined in `ControlSystems`
Stacktrace:
 [1] top-level scope
   @ ~/.julia/packages/ControlSystems/KuzoR/src/simulators.jl:49
 [2] include(mod::Module, _path::String)
   @ Base ./Base.jl:557
 [3] include(x::String)
   @ ControlSystems ~/.julia/packages/ControlSystems/KuzoR/src/ControlSystems.jl:1
 [4] top-level scope
   @ ~/.julia/packages/ControlSystems/KuzoR/src/ControlSystems.jl:22
 [5] include
   @ ./Base.jl:557 [inlined]
 [6] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt128}}, source::String)
   @ Base ./loading.jl:2881

As far as I understand, it is a problem related to ControlSystems dependencies, thus won’t help fixing ControlSystems version, I should fix the version of all its dependencies.

Deleting the manifest and doing resolve was not helping either. The only way I found out to unlock my environemnt was to go into the Manifest and change back all the package versions.

Manually editing the manifest isn’t a good idea - better to just do ]undo if something went wrong with ]up

3 Likes

There’s an issue at ControlSystems github about this: ControlSystems.jl fails to compile · Issue #1020 · JuliaControl/ControlSystems.jl · GitHub

Apparently it has been fixed in a recent version.

1 Like

Thanks, I didn’t know about the undo!

Wasn’t working for me, and it broke on the ] up, so unless the fix was done on the next version (i.e. 1.17.x instead of 1.16.y), I don’t know why it didn’t update.

Do you know an alternative to ControlSystems?

I’ve never used ControlSystems.jl, and know of no alternative. I suggest you file an issue at their github at GitHub · Where software is built

@baggepinnen

Well, you should always use a local project like explained here: Working with Julia projects | Julia programming notes

If you have a local Project.toml file, add a compat section (also explained in the link above) and enter in this [compat] section the version numbers of the packages you need in the combination that works well, like this:

[compat]
ControlSystemsBase = "~1.15.1"

You can use ~ or = in front of the version number. ~ allows minor updates.

If you have a Project.toml file with a correct compat section you can always use Pkg.update() to update the indirect dependencies and nothing should break.

Furthermore, if you have a well tested state of your project, make a backup copy of your Manifest.toml file, like this:

cp Manifest.toml Manifest-v1.11.toml.default

and add this copy to git.

Furthermore, often ControlSystemsBase.jl is good enough (and much faster to install) then ControlSystems.jl .

If you did these steps and still have problems, please post the output of

using Pkg
Pkg.status()

You asked for alternatives to ControlSystems.jl . Well, we cannot answer this question if we do not know which problem you are trying to solve. If you tell us more, we might be able to suggest alternatives.

1 Like

The current release is 1.15.1 and includes the fix to the issue mentioned above. I have no problems using it on the latest Julia release:

(@v1.11) pkg> activate --temp

(jl_AYjc7p) pkg> add ControlSystems
   Updating `...\AppData\Local\Temp\jl_AYjc7p\Project.toml`
  [a6e380b2] + ControlSystems v1.15.1
(...)

Precompiling project...
  155 dependencies successfully precompiled in 145 seconds. 95 already precompiled.
  1 dependency had output during precompilation:
┌ LinearSolve
│   Downloading artifact: MKL
└

(jl_AYjc7p) pkg> st
Status `...\AppData\Local\Temp\jl_AYjc7p\Project.toml`
  [a6e380b2] ControlSystems v1.15.1

julia> using ControlSystems

So if something isn’t working for you you’ll have to show the outputs of versioninfo() and ]st for others to try and reproduce your issue.

One option you can consider:

  1. Check your Project.toml and Manifest.toml files into source control. Also record what Julia version you are using (newer Julia versions store that info in the manifest for you).
  2. Just before you do pkg> up, commit your current project and manifest files. At this point, you can also push to a remote (e.g. a private GitHub repo) if you want.
  3. Do the pkg> up, and then see if anything breaks.
  4. If something has broken, just revert to the previous commit, because you know that commit has a working manifest.

I’d probably recommend using Git as your source control system. But this approach should in theory work with any source control system.

1 Like

To save some clicks, the reason is that ControlSystems formerly did import OrdinaryDiffEq: DiffEqBase, but an update to OrdinaryDiffEq switched from importing DiffEqBase (directly at least) to the lightweight SciMLBase. The other modules and types a package imports and extends are internal details subject to change unless documented to be stable user-level features, and as far as I can tell, the heavy re-exporting makes it so that users of OrdinaryDiffEq aren’t intended to directly reference DiffEqBase. ControlSystems is free to separately use DiffEqBase as an internal dependency, which is the fix, though it could potentially switch to SciMLBase in the future.

Bit of an aside, importing a likely internal dependency of a direct dependency is currently the typical practice in extensions that can’t safely import dependencies other than its trigger packages. Besides being unfeasible for wholly independent internal types (I might want to crunch StaticArrays in an extension for packages that don’t use it), a direct dependency changing or omitting an internal import can break that extension forever.

pkg> ?add

It’s good to use pkg> add --preserve=all or some of the other options there. Or for

up --preserve=<all/direct/none>

I wish this was the default in Julia, at least an option to never downgrade… which is likely your problem.

Save your Manifest.toml file, then you at least know how your exact working setup was like, and you can easily revert.

I add packages to my (global) environment like crazy (or have to test out intriguing packages), and I’m sure it doesn’t help. I’m adopting a better workflow since it’s a bad habit.

Sometimes downgrades are a problem, not sure about this one, any downgrade seems like a step backwards to me, so I want to eliminate the possibility (but then maybe you can’t install until you figure out what’s blocking and fixing that):

⌃ [f6369f11] ↓ ForwardDiff v1.1.0 ⇒ v0.10.38

]activate --temp is your friend

4 Likes