Skip to content

RFC: Developing package configuration system (package options) outside Base and Pkg? #1378

@tkf

Description

@tkf

I realized that package options can be implemented outside Base and Pkg so here is my proof of concept implementation: https://github.com/tkf/PkgOptions.jl. Combined with conditional dependencies #1285, I think the examples in JuliaLang/Juleps#38 and #977 (cc @Roger-luo) can be covered (feature flags are just boolean package options). Quoting the README:

Features

  • Project/environment-local per-package configuration options.
  • Precompilation is triggered when package options are changed.
  • Minimal dependency (PkgOptionsLoader) for a package to support package options.

Installation

pkg> add https://github.com/tkf/PkgOptionsLoader.jl.git

pkg> add https://github.com/tkf/PkgOptions.jl.git

pkg> add https://github.com/tkf/PkgOptionsDemo.jl.git  # a demo

Usage

End-users

Use PkgOptions.set(pkg; ...) to configure package options for package pkg:

julia> using PkgOptions

julia> PkgOptions.set(:PkgOptionsDemo, some_option=true)

julia> using PkgOptionsDemo
       PkgOptionsDemo.pkgoptions
[ Info: Precompiling PkgOptionsDemo [bb3b8621-5970-400b-8acd-051caadabee1]
Dict{String,Any} with 1 entry:
  "some_option" => true

Note that package options are precompile-time options. You need to reload package to re-configure it.

To use the default option, remove the package option by:

julia> PkgOptions.rm(:PkgOptionsDemo)

See more details in the documentation.

Package authors

To support package options, use PkgOptionsLoader.@load to load package options (a Dict{String,Any}). For example, PkgOptionsDemo.jl used above in the demo is defined as

module PkgOptionsDemo
using PkgOptionsLoader
const pkgoptions = PkgOptionsLoader.@load
end

See more details in the PkgOptionsLoader.@load documentation.

How it works

PkgOptions.set, PkgOptionsLoader.@load, etc. read and write the package options in a TOML file at

~/.julia/options/$project_slug/$package_slug/$package_name.toml

where

  • $project_slug is a hash determined by the project path (Base.active_project()).
  • $package_slug is a hash determined by the UUID of the package whose options are configured.
  • $package_name is the name of the package whose options are configured.
  • ~/.julia may be different if you configure Base.DEPOT_PATH[1]

Changing the TOML file triggers precompilation using Base.include_dependency mechanism.

See more in the documentation: https://tkf.github.io/PkgOptions.jl/dev

What do you think about the approach? Does it have some limitations? What are the alternatives?

A possible improvement would be to increase reproducibility. I think there are several ways to do it (e.g., reflecting options in Project.toml, maybe using format like #458 (comment)).

I think actually the main observation that this can be developed outside Base and Pkg. It's good because the implementation and protocol can be iterated faster in the wild.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions