  Nearly every popular programming language comes with one or more package
managers. The software packages distributed by such package managers form large
software ecosystems. These packaging ecosystems contain a large number of
package releases that are updated regularly and that have many dependencies to
other package releases. While packaging ecosystems are extremely useful for
their respective communities of developers, they face challenges related to
their scale, complexity, and rate of evolution. Typical problems are backward
incompatible package updates, and the risk of (transitively) depending on
packages that have become obsolete or inactive. This manuscript uses the
libraries.io dataset to carry out a quantitative empirical analysis of the
similarities and differences between the evolution of package dependency
networks for seven packaging ecosystems of varying sizes and ages: Cargo for
Rust, CPAN for Perl, CRAN for R, npm for JavaScript, NuGet for the .NET
platform, Packagist for PHP, and RubyGems for Ruby. We propose novel metrics to
capture the growth, changeability, resuability and fragility of these
dependency networks, and use these metrics to analyse and compare their
evolution. We observe that the dependency networks tend to grow over time, both
in size and in number of package updates, while a minority of packages are
responsible for most of the package updates. The majority of packages depend on
other packages, but only a small proportion of packages accounts for most of
the reverse dependencies. We observe a high proportion of fragile packages due
to a high and increasing number of transitive dependencies. These findings are
instrumental for assessing the quality of a package dependency network, and
improving it through dependency management tools and imposed policies.
