Obtaining source locations and licenses recursively for a derivation

Checking what licenses apply to a binary is not easy. With Nix we declare the license that applies to a source, although we declare it in the derivation of the built artifact.

I’m looking for a solution that can yield for me for a derivation what components potentially leave traces, what source those are built from, and what licenses apply. Clearly, recursion plays a role here.

We do not declare in our expressions what parts leave traces. We do know that buildInputs are run-time dependencies and are expected to leave traces. Certain nativeBuildInputs may leave traces as well, and thus need to be considered. Would it make sense to declare which dependencies leave traces? If so, where? Maybe nativeBuildInputsViral, or in the actual derivation that could be viral. The latter I don’t think will work because a given derivation does not always have to be viral. Cases where one points directly to derivations are difficult to handle.

Of course, one could also take the other way around. Build it, and check run-time dependencies. This, however, does not cover the cases where one generated or copied in parts.

Maybe consider then the run-time derivations obtained after build, along with manual checking of nativeBuildInputs?

Also, nix-show-derivation -r yields derivation information recursively, however, unfortunately meta is not included there.

1 Like

I’m facing pretty much the same issue here. I wan’t to bundle some program with (patched) libs using nix-bundle (which is perfect for this use case!).

I can find out what goes in the bundle easily using commands like

nix-store -q --tree $(nix-instantiate -A stm32sign default.nix) | \
sed -n 's!.*\(/nix/store.*.drv\).*!\1!p' | sort -u | \
xargs -I {} -n 1 nix show-derivation {} | jq -r '.[] | .env.pname, .env.version' | sort -u 

But there seems no good way to get back the original attribute sets and from these the meta.license fields.

Going forward from the attribute in my default.nix is also far from straightforward (and might pull in licenses from compilers, which are not relevant for the bundle itself).

Maybe someone played with recursing through all attributes in a set (including unpacking lists etc.). Then some matching between list generated by the approach above and by recursing might lead to a viable solution.

2 Likes

I happen to be interested in the same topic so let me ask do we have any improvements since then? Can we list licenses of a closure of a package using /nix/store/… as an entry point?

If you are working in a Nix flake, you can add a package to your flake, that would do the following:

Using Nix code, iterate all attributes in buildInputs and nativeBuildInputs of an attribute, and do the following for each:

let
  getLicensesRecursivly = pkg: [
    # TODO: Generate a list of these, for all inputs, recursively
    {
      inherit (pkg) pname version;
      inherit (pkg.meta) license;
    }
  ];
  ourLicensesJSON = builtins.toJSON (getLicensesRecursivly ourPackage);
  # where pkgs is Nixpkgs
  inherit (pkgs) lib;
in ourLicenses = stdenvNoCC.mkDerivation {
  pname = "licenses";
  inherit version;
  buildCommand = ''
    mkdir $out
    echo ${lib.escapeShellArg ourLicensesJSON} > $out/licenses.json
  ''; ourPackage;
};

You could of course iterate that list in any other way you can imagine, or perform all kind of Nix logic to check that all licenses are free & non-GPL etc. You could also fail the build in case a license is not MIT, with something like this:

buildCommand = if (checkAllLicensesAreOK ourPackage) then ''
   echo All licenses are free and non-GPL > $out
'' else ''
  echo Licenses of the following packages are not OK:
  echo ${getNotOklLicenses ourPackage}
  exit 2
'';

Where the functions getNotOkLicenses and checkAllLicensesAreOK iterate the list generated by getLicensesRecursivly described above.

Another approach, would be to write for a derivation a disallowedReferences list, that would iterate buildInputs and nativeBuildInputs with a Nix function as described above. (Use finalAttr.finalPackage) - this would fail the build in case some of the inputs have non-free licenses or whatever you decide in getNotOklLicenses. The bit annoying downside of this is that it will fail the build only in the end of it. However, this behavior may be useful in particular for cases where you use a non-free/GPL package in nativeBuildInputs, and you won’t mind it be there, if the finalPackage doesn’t reference it.

1 Like