Best practice: develop and adjust own package / precompilation

A am currently using Julia for a project, which I splitted into two different packages. Each of these package has it`s own Manifest/Project files.
There is an “application” section, in which I use the functions from these packages with

using MyPackage1, MyPackage2

When I do this, the precompilation takes a lot of time. That would be fine, if I would be finished working on ‘MyPackage1’. However, when I do small changes, and re-type

‘using MyPackage1’

in the REPL or restart the REPL after the changes, precompilation is starting again. Is this un-avoidable? What is the best practice to set up the project?

As an alternative, I kept working in the local environment of ‘MyPackage1’. However, here Julia keeps compiling other depencies on each Start (like Plots.jl).

The waiting times make it practically impossible to get anything done. How can I avoid that?

2 Likes

Hi,

Small question: are you using Revise.jl?

If that is the case, you don’t need to restart the repl and no need to type using MyPackage again and again.

Best

1 Like

Also:

“It is sometimes helpful during module development to turn off incremental precompilation. The command line flag --compiled-modules={yes|no} enables you to toggle module precompilation on and off. When Julia is started with --compiled-modules=no the serialized modules in the compile cache are ignored when loading modules and module dependencies.”

3 Likes

Quoting the docs,

Precompilation cache files store definitions of modules, types, methods, and constants. They may also store method specializations and the code generated for them, but this typically requires that the developer add explicit precompile directives or execute workloads that force compilation during the package build.

However, if you update the module’s dependencies or change its source code, the module is automatically recompiled upon using or import.

In short, whenever you using or import after editing the source code, you are doing a change as big as reevaluating a module. It’s quicker to make small changes like interactively replacing a method in a REPL session. Some changes can’t be made (editing a struct’s field structure), and small edits out of order can be different from rerunning a whole thing, but you can get a lot of work done through small interactive changes between the big overhauls. Revise.jl is useful for making source code edits automatically perform those small changes in a REPL session, so you don’t have to repeat it manually in the session.

1 Like

Thanks Olivier! For some changes that helped! However, some actioins (like changing definitions of structs) seem to require a restart

Ok, that helps! I was mainly working on structs, this is why I got frustrated. If the rest works with re-definition, that will be faster!

Glad it helped!

Indeed, Revise.jl cannot track the changes in structs.

To handle this, there are a few workarounds.
What I prefer is to make a new struct with different names. MyStruct1, MyStruct2.
Like this I can still test the previous versions.

Other people prefer to use named tuples until they are satisfied with the result and then change to structs.

Here is one of the many discussions on Revise.jl and structs:

2 Likes

I like to make throwaway structs when there’s not yet a lot of methods to replace for them. If my methods are annotated with abstract types and I just need to make interface methods for each concrete type, that could buy me some time. But it’s good to reach a conclusion on the struct’s fields sooner than later.