Skip to main content

Crate license_fetcher

Crate license_fetcher 

Source
Expand description

Fetch licenses of dependencies at build time and embed them into your program.

license-fetcher is a package for fetching actual license texts from the cargo source directory for packages that are compiled with your project. It does this in the build step in a build script. This means that the heavy dependencies of license-fetcher aren’t your dependencies!

§Simple Example

Import license-fetcher as a normal AND as a build dependency:

cargo add --build --features build license-fetcher
cargo add license-fetcher

src/main.rs

use license_fetcher::prelude::*;
fn main() {
    let package_list = read_package_list_from_out_dir!().unwrap();
}

build.rs

use license_fetcher::prelude::*;

fn main() {
    // Config with environment variables set by cargo, to fetch licenses at build time.
    let config: Config = ConfigBuilder::from_build_env()
        .build()
        .expect("failed to build configuration");

    let packages: PackageList =
        package_list_with_licenses(&config).expect("failed to fetch metadata or licenses");

    // Write packages to out dir to be embedded.
    packages
        .write_package_list_to_out_dir()
        .expect("failed to write package list");

    // Rerun only if one of the following files changed:
    println!("cargo::rerun-if-changed=build.rs");
    println!("cargo::rerun-if-changed=Cargo.lock");
    println!("cargo::rerun-if-changed=Cargo.toml");
}

For a more advanced example visit the build module documentation.

§Adding Dependencies that are not Packages

Sometimes we have dependencies that are not packages. For these dependencies license-fetcher cannot automatically generate information. These dependencies can be added manually:

use std::fs::read_to_string;
use std::concat;

use license_fetcher::prelude::*;

fn main() {
    // Config with environment variables set by cargo, to fetch licenses at build time.
    let config: Config = ConfigBuilder::from_build_env()
        .build()
        .expect("failed to build configuration");

    // `packages` does not hold any licenses!
    let mut packages: PackageList = package_list(&config)
        .expect("failed to fetch metadata");

    let other_dependency = Package::builder("other dependency", "0.1.0")
        .add_author("Me")
        .description("A dependency that is not a rust package.")
        .add_license_text(
            "other dependency license",
            read_to_string(concat!(env!("CARGO_MANIFEST_DIR"), "/LICENSE"))
            .expect("failed reading license of other dependency")
        )
        .build();

    packages.push(other_dependency);

    // Write packages to out dir to be embedded.
    packages.write_package_list_to_out_dir().expect("failed to write package list");

    // Rerun only if one of the following files changed:
    println!("cargo::rerun-if-changed=build.rs");
    println!("cargo::rerun-if-changed=Cargo.lock");
    println!("cargo::rerun-if-changed=Cargo.toml");
}

§Features

  • build enables license metadata parsing and license text fetching.
  • serde enables the derivation of Serialize and Deserialize for Package and PackageList.

§Error Handling

Handling errors in license-fetcher is more or less optional. If you work with expect and unwrap, then you might be faced with the possibility of fatal compilation errors. If you only expect to build your project in CI, this might not be much of a problem. If you expect users to compile your project, especially for uncommon platforms, your users might face these compilation errors. The documentation of the build module offers and example on how to encounter this conundrum with a dummy file being written on failure. You could also handle the errors encountered, which the following paragraphs will discuss.

The ConfigBuilder returns on calling the build method a result with the ConfigBuilderError. This error contains a human readable verbose backtrace and a machine readable, recoverable error kind (CEK).

The package_list and package_list_with_licenses functions return a result with the LicenseFetcherError. This error as well has a verbose human readable error message as well as a machine readable error kind (EK). The documentation of EK has multiple examples on how errors can be handled.

The read_package_list_from_out_dir macro on the other hand returns UnpackError, which can be normally handled with match clauses (see the build module documentation for an example).

Modules§

buildbuild
Functions for fetching metadata and licenses and writing license data.
error
Wrapper around deserialization and decompression errors during unpacking of a serialized and compressed PackageList.
prelude
Prelude of license-fetcher.

Macros§

read_package_list_from_out_dir
Embed and decode a PackageList, expected to have been placed in $OUT_DIR.

Structs§

Package
Struct holding information like package name, authors and of course license texts.
PackageBuilder
A builder for Package.
PackageList
Holds information of all packages and licenses used for a release build.

Constants§

OUT_FILE_NAME
The file name used for writing and reading the serialized package list.