Skip to content

PyJulia/PyCall.jl not working well with new compilation cache management in Julia 0.7/Pkg3.jl #28518

@tkf

Description

@tkf

I'm moving the discussion from JuliaPy/pyjulia#173 to gather more attention. I also describe in the last paragraphs how it may help not only PyJulia users but also other Julia users.

(@stevengj, @Keno, please correct me or add more details if I'm missing something)

Prior to Julia 0.7, PyJulia users could use multiple Python interpreters without rebuilding PyCall.jl (PyJulia depends heavily on PyCall.jl) against each Python interpreters. Considering it's a common practice to have multiple Python virtual environments (with venv/virtualenv/conda), being able to use PyJulia without recompiling PyCall.jl every time is an important feature. However, supporting this feature in Julia ≥ 0.7 seems hard.

(Some details: Just to be clear, not all PyJulia users will notice this effect. Notably, Windows or macOS users only using Python 3 (or only using Python 2...) are unaffected. Linux users only using dynamically linked Python 3 (or 2) are also fine. However, Linux users using statically linked Python, such as the ones distributed by Ubuntu and Anaconda, will not be able to use PyJulia. I think those platforms are popular enough to pay a special attention.)

PyJulia relies on Base.LOAD_CACHE_PATH in Julia 0.6 to separate the cache of PyCall.jl. It inserts a private path to Base.LOAD_CACHE_PATH[1] if the Python interpreter in which PyJulia is loaded is incompatible with the Python interpreter with which PyCall.jl is configured:

# Add a private cache directory. PyCall needs a different
# configuration and so do any packages that depend on it.
self._call(u"unshift!(Base.LOAD_CACHE_PATH, abspath(Pkg.Dir._pkgroot()," +
    "\"lib\", \"pyjulia%s-v$(VERSION.major).$(VERSION.minor)\"))" % sys.version_info[0])

--- https://github.com/JuliaPy/pyjulia/blob/18d98e5b1b616a4d663273cc36cdd835ab0b33da/julia/core.py#L357-L360

This "hack" doesn't work in Julia ≥ 0.7 as Base.LOAD_CACHE_PATH is gone now. Also, reading how cache_file_entry is used to locate the .ji files, I couldn't find a way to implement a new "hack" other than duplicating the whole DEPOT_PATH[1].

julia/base/loading.jl

Lines 594 to 608 in d038f2f

cache_file_entry(pkg::PkgId) = joinpath(
"compiled",
"v$(VERSION.major).$(VERSION.minor)",
pkg.uuid === nothing ? "$(pkg.name).ji" : joinpath(pkg.name, "$(package_slug(pkg.uuid)).ji")
)
function find_all_in_cache_path(pkg::PkgId)
paths = String[]
entry = cache_file_entry(pkg)
for depot in DEPOT_PATH
path = joinpath(depot, entry)
isfile_casesensitive(path) && push!(paths, path)
end
return paths
end

But creating a new DEPOT_PATH[1] for each incompatible Python interpreter type is rather overkill and ignores Pkg3 working hard to de-duplicate resources. It would be really nice to have a direct support from Julia and Pkg3, if it is feasible.

An idea: "build option" support

I think one way to directly support it is to add "build option" support in Julia and Pkg3. What I mean by "build option" is something that altering it changes the precompilation cache. Currently Julia packages do this via environment variables. Concrete examples are PYTHON of PyCall.jl and CONDA_JL_HOME of Conda.jl. If those options can be directly configured by Project.toml file, and if compilation cache paths depend on such options, PyJulia can just create a new Project.toml with appropriate options and launch a new Julia interpreter. Importantly, the compilation cache path of a package has to depend also on the build options of all its (direct and indirect) dependencies.

I think the "build option" support can help other Julia users (who do not use PyJulia) too. For example, you can change CONDA_JL_HOME for a particular Project.toml to tweak versions of external libraries provided via Conda.jl without contaminating other projects. (Maybe similar benefits can be gained via BinaryProvider.jl too?) I think supporting 32-bit and 64-bit Julia JuliaLang/Pkg.jl#93 can also be done by changing "build option" of the "root" julia package. I suppose then it makes sense for deps directories to depend on "build options" too (JuliaLang/Pkg.jl#93 (comment)).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions