May 14, 2021 Julia
3. Add and remove extension packages
4. Install an unregistered extension package
Julia has a built-in package management system that allows you to manage packages, and of course, you can also use your operating system to bring your own, or compile from source.
You can http://pkg.julialang.org list of all registered packages (a mechanism for publishing packages) in the http://pkg.julialang.org of the page.
All package management commands are included
Pkg
module, and Julia's Base install introduces
Pkg
A summary of all your installed packages can be printed using the
Pkg.status()
At first, you didn't install any packages:
julia> Pkg.status()
INFO: Initializing package repository /Users/stefan/.julia/v0.3
INFO: Cloning METADATA from git://github.com/JuliaLang/METADATA.jl
No packages installed.
When you first run
Pkg
your package directory (all packages are installed in a unified directory) is automatically initialized
Pkg
wants to have a directory
Pkg.status()
Here is a simple example that already has a small number of installed packages:
julia> Pkg.status()
Required packages:
- Distributions 0.2.8
- UTF16 0.2.0
Additional packages:
- NumericExtensions 0.2.17
- Stats 0.2.6
These packages are registered versions and managed
Pkg
Packages installed can be a more complex "state" that indicates the correct version through Comments, which we explain when we encounter these "States" and "Comments."
For programming reasons,
Pkg.installed()
a dictionary that corresponds to the name of the installed package and the version it is now using:
julia> Pkg.installed()
["Distributions"=>v"0.2.8","Stats"=>v"0.2.6","UTF16"=>v"0.2.0","NumericExtensions"=>v"0.2.17"]
Julia's package management is a little different because it's life rather than necessity. T his means that if you tell it what you want, it will know what version to install (or remove) to selectively meet those needs - the lowest available. S o instead of installing a package, you just add it to the requirements list and then "fix" what needs to be installed. In particular, this means that if some packages have been installed because they were needed by the previous version of what you wanted, and an updated version no longer has that requirement, the update will actually remove that package.
Your package requirements are in
~/.julia/v0.3/REQUIRE
Y
ou can manually edit the file and
Pkg.resolve()
or remove the package selectively to meet your needs, or you can do
Pkg.edit()
which will
REQUIRE
(configured via EDITOR or
EDITOR
environment variables) in your editor, and
Pkg.resolve()
necessary.
VISUAL
If you just want to add or remove a single package of requirements, you can also use the
Pkg.add
Pkg.rm
which add or remove a single requirement
REQUIRE
and
Pkg.resolve()
You can add a package to the requirements list with the
Pkg.add
function, and the package and all the packages on which it depends will be installed:
julia> Pkg.status()
No packages installed.
julia> Pkg.add("Distributions")
INFO: Cloning cache of Distributions from git://github.com/JuliaStats/Distributions.jl.git
INFO: Cloning cache of NumericExtensions from git://github.com/lindahua/NumericExtensions.jl.git
INFO: Cloning cache of Stats from git://github.com/JuliaStats/Stats.jl.git
INFO: Installing Distributions v0.2.7
INFO: Installing NumericExtensions v0.2.17
INFO: Installing Stats v0.2.6
INFO: REQUIRE updated.
julia> Pkg.status()
Required packages:
- Distributions 0.2.7
Additional packages:
- NumericExtensions 0.2.17
- Stats 0.2.6
The first thing to do here is to add
Distributions
~/.julia/v0.3/REQUIRE
file:
$ cat ~/.julia/v0.3/REQUIRE
Distributions
It then runs
Pkg.resolve()
which lead
Distributions
be installed because it is required and not installed.
As previously stated, you can do the same thing by manually editing your
~/.julia/v0.3/REQUIRE
file and then
Pkg.resolve()
$ echo UTF16 >> ~/.julia/v0.3/REQUIRE
julia> Pkg.resolve()
INFO: Cloning cache of UTF16 from git://github.com/nolta/UTF16.jl.git
INFO: Installing UTF16 v0.2.0
julia> Pkg.status()
Required packages:
- Distributions 0.2.7
- UTF16 0.2.0
Additional packages:
- NumericExtensions 0.2.17
- Stats 0.2.6
This is the same
Pkg.add("UTF16")
that
Pkg.add
does not change ASK until
REQUIRE
so if there is a problem,
REQUIRE
will be left as
Pkg.add
REQUIRE
format of the REQUIRE file is described in
Requirements Specification;
When you decide you don't want to have another package, you
Pkg.rm
to remove its
REQUIRE
from the REQUIRE file:
julia> Pkg.rm("Distributions")
INFO: Removing Distributions v0.2.7
INFO: Removing Stats v0.2.6
INFO: Removing NumericExtensions v0.2.17
INFO: REQUIRE updated.
julia> Pkg.status()
Required packages:
- UTF16 0.2.0
julia> Pkg.rm("UTF16")
INFO: Removing UTF16 v0.2.0
INFO: REQUIRE updated.
julia> Pkg.status()
No packages installed.
Again, this is similar to
REQUIRE
file to remove the line with the package name and then
Pkg.resolve()
change the collection of installation packages to match. A
lthough
Pkg.add
Pkg.rm
convenient for adding and removing individual packages, when you want to add or remove multiple
Pkg.edit()
change
REQUIRE
update your package as the situation is.
Pkg.edit()
roll back
REQUIRE
content if
Pkg.resolve()
- you have to run
Pkg.edit()
modify the document content.
Because package management uses git internally to manage the package git repository,
Pkg.add
users may run into protocol issues (such as behind a firewall).
The next command can be run on the command line to tell git to use the 'https' instead of the 'git' protocol when cloning the repository.
git config --global url."https://".insteadOf git://
The Julia package is simply a git repository, is
cloneable
on any git-supported protocol, and contains Julia code that follows specific layout conventions. T
he official Julia package is
registered in the METADATA.jl
warehouse and is available where it can be found. I
n previous paragraphs,
Pkg.add
and
Pkg.rm
registered packages, but package management can also install and use unregistered packages. T
o install an unregistered package,
Pkg.clone(url)
url
a git URL where the package can be cloned:
julia> Pkg.clone("git://example.com/path/to/Package.jl.git")
INFO: Cloning Package from git://example.com/path/to/Package.jl.git
Cloning into 'Package'...
remote: Counting objects: 22, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 22 (delta 8), reused 22 (delta 8)
Receiving objects: 100% (22/22), 2.64 KiB, done.
Resolving deltas: 100% (8/8), done.
By convention, Julia repositories are
.jl
.git
indicates a "naked" git repository), which prevents them from colliding with warehouses in other languages and makes Julia's packages easy to find in search engines.
When the package is
.julia/v0.3
directory, however, the extension is redundant, so we leave it behind.
If unregistered packages contain a REQUIRE file at the
REQUIRE
the file will be used to determine which registered packages the unregistered packages depend on, and they will be installed automatically.
Unregistered packages have the same resolution logic as registered packages, so installed package versions will be adjusted if necessary to meet the needs of registered and unregistered packages.
The official set of packages is https://github.com/JuliaLang/METADATA.jl, but individuals and organizations can simply use a different metadata warehouse. T his allows the package to be automatically installed for control. We can only allow audits to pass and approve package versions and make private packages and forks available.
When a package developer releases a new registered package version that you are using, of course, you want a new version.
For the latest and best package version,
Pkg.update()
:
julia> Pkg.update()
INFO: Updating METADATA...
INFO: Computing changes...
INFO: Upgrading Distributions: v0.2.8 => v0.2.10
INFO: Upgrading Stats: v0.2.7 => v0.2.8
The first step in updating the package is to put the new changes in
~/.julia/v0.3/METADATA
see if a new registration package version has been released. A
fter that,
Pkg.update()
the package that is checked on a branch by some changes from the upstream library pull of the package and does not dirty (for example, no changes to the file under git). U
pstream changes are applied only if it is necessary if it is not necessary to merge or re-base addresses - for example,
if the branch is "fast-forwarded".
I
f the branch is not fast-forwarded, assume that you are using it and change the repository yourself.
Finally, the update process recalculates a collection of the best package versions to install to meet your top-level needs and "fix" package requirements. The package is considered fixed if it is one of the following:
1.
Unregistered:
The package is not in
METADATA
- you
Pkg.clone
2
.
Checked out:
Package warehouse on a development branch.
3.
Dirty: The
file has been modified in the warehouse.
If any of these appear, the package manager is not free to change the installed package version, so its requirements must be met, regardless of the other package version it selects.
The
~/.julia/v0.3/REQUIRE
of modified packages are used to determine what should be installed.
You may want to use the
master
the package instead of registering one of the versions. T
here may be modifications or features on master that you need and are not published on any registered version, or you may be a developer of a
master
or some other development branch.
In these examples,
master
you can check the master branch of pkg or
Pkg.checkout(pkg,branch)
by
Pkg.checkout(pkg)
to check some other branches:
pkg
julia> Pkg.add("Distributions")
INFO: Installing Distributions v0.2.9
INFO: Installing NumericExtensions v0.2.17
INFO: Installing Stats v0.2.7
INFO: REQUIRE updated.
julia> Pkg.status()
Required packages:
- Distributions 0.2.9
Additional packages:
- NumericExtensions 0.2.17
- Stats 0.2.7
julia> Pkg.checkout("Distributions")
INFO: Checking out Distributions master...
INFO: No packages to install, update or remove.
julia> Pkg.status()
Required packages:
- Distributions 0.2.9+ master
Additional packages:
- NumericExtensions 0.2.17
- Stats 0.2.7
Once
Distributions
is
Pkg.add
it is on the latest registered version -
0.2.9
T
hen after
Pkg.checkout("Distributions")
you can see
Pkg.status()
that
Distributions
better than
0.2.9
on an unregistered version.
Indicated by the "pseudo-version"
0.2.9+
plus.
When you examine an unregistered package version, the copy status of the REQUIRE file in the
REQUIRE
higher than any other requirement for registration in
METADATA
important for developers to keep this file correct and timely, reflecting the real needs of the current package version. I
f the
REQUIRE
file in the package repository is incorrect or missing, dependencies may be removed when the package is checked out.
This file is also used to populate the newly released package version if you use
Pkg
for this by Pkg (described below).
When you decide that you no longer want a package to be checked out on a branch, you
Pkg
to "release" it back under the control of the package manager.
julia> Pkg.free("Distributions")
INFO: Freeing Distributions...
INFO: No packages to install, update or remove.
julia> Pkg.status()
Required packages:
- Distributions 0.2.9
Additional packages:
- NumericExtensions 0.2.17
- Stats 0.2.7
After that, because the package is on top of a registered version and not on a branch, its version is updated to be published as the registered version of the package.
If you want to pin a package on a specified version so that calling
Pkg.update()
change the version in which the package is located,
Pkg.pin
feature:
julia> Pkg.pin("Stats")
INFO: Creating Stats branch pinned.47c198b1.tmp
julia> Pkg.status()
Required packages:
- Distributions 0.2.9
Additional packages:
- NumericExtensions 0.2.17
- Stats 0.2.7 pinned.47c198b1.tmp
After that,
Stats
will remain pin in
0.2.7
- or
47c198b1
but that's the same since the version was permanently connected to a given git hash.
Pkg.pin
by creating a throw-off branch for the submission of the pin package you want.
By default, it pins a package under the current commit, but you can select a different version by passing the second argument:
julia> Pkg.pin("Stats",v"0.2.5")
INFO: Creating Stats branch pinned.1fd0983b.tmp
INFO: No packages to install, update or remove.
julia> Pkg.status()
Required packages:
- Distributions 0.2.9
Additional packages:
- NumericExtensions 0.2.17
- Stats 0.2.5 pinned.1fd0983b.tmp
The
Stats
is now pinned when it commits
1fd0983b
which is consistent
0.2.5
When you decide on a "unpin" package and have the package manager update it again,
Pkg.free
as if you wanted to leave any branch:
julia> Pkg.free("Stats")
INFO: Freeing Stats...
INFO: No packages to install, update or remove.
julia> Pkg.status()
Required packages:
- Distributions 0.2.9
Additional packages:
- NumericExtensions 0.2.17
- Stats 0.2.7
Julia's package manager is designed so that when you have a package to install, you can view its source code and complete development history. Y ou can also make changes to packages, commit them using git, and simply make changes and enhancements. Similarly, the system is designed so that if you want to create a new package, the easiest way to do this is within the infrastructure provided by the package manager.
Packages that are not on the branch will also be marked as dirty if you make changes in the repository, but that's a relatively rare thing.