Nix package creation: install a font that is not yet supported

The Nix package collection is large with over 60,000 packages. But chances are, sometimes the package you need isn't available. You have to integrate it yourself.

I needed some fonts that weren't already inside nixpkgs. In Nix, a font is distributed as a package like any other software. One of the fonts to be installed is Dancing script. As of this writing, filing nixpkgs reveals no relevant match:

nix search nixpkgs dancing 

Whether your system is running NixOS or just using the Nix package manager, as I do with macOS, creating a Nix package isn't always that difficult. The package we will create works for every Nix distribution. I provide commands for Linux running NixOS and for macOS running nix-darwin. It sure is scary. You have to get your hands dirty and write some code. However, given the nature of Nix, most of us already have some custom Nix configuration files. I'll illustrate the process of creating and sharing a new Nix package with the community.

Font installation with NixOS

NixOS suggests many font pack. For a font to be visible to all your applications, it must be registered in the fonts.fonts option list. For example from your main configuration.nix file:

{ config, pkgs, ... }:

{
  imports =
    [
      ./david-framework-hardware.nix
    ];
  
  fonts.enableFontDir = true;
  fonts.fonts = with pkgs; [    dejavu_fonts    inter  ];  
}

Not all fonts are available from nixpkgs. How to install a font that is not yet supported inside fonts.fonts option list by creating our package. When the package is ready, we publish it!

Finding a suitable example

The NixOS documentation is confusing. It is divided into several places. Sometimes it lacks basic information and sometimes it goes so deep into the details that it is difficult to understand. Reading the source code is a good and recommended approach to learn about the language and to customize your environment.

On every system, installing a font is all about downloading it and placing it in the correct system location. Let's find out how other fonts are installed. For example Inter typeface. Search for inter by Nix search. There is a source link which points to the package inside the nixpkgs repository:

{ lib, fetchzip }:

let
  version = "3.19";
in fetchzip {
  name = "inter-${version}";

  url = "https://github.com/rsms/inter/releases/download/v${version}/Inter-${version}.zip";

  postFetch = ''
    mkdir -p $out/share/fonts/opentype
    unzip -j $downloadedFile \*.otf -d $out/share/fonts/opentype
  '';

  sha256 = "sha256-8p15thg3xyvCA/8dH2jGQoc54nzESFDyv5m47FgWrSI=";

  meta = with lib; {
    homepage = "https://rsms.me/inter/";
    description = "A typeface specially designed for user interfaces";
    license = licenses.ofl;
    platforms = platforms.all;
    maintainers = with maintainers; [ demize dtzWill ];
  };
}

The package contains some metadata such as the package name, a link to the official project and a description. The url and sha256 used by fetchzip to download the font files. Each .otf the file is extracted from the zip archive to $out/share/fonts/opentype folder.

Create a package

Watching Dancing script repository, there is no download available. Instead of fetchzip function used to download a .zip archive we use fetchFromGitHub function to download the snapshot of a GitHub repository.

The code is organized in different ways, with different characteristics, but it achieves the same purpose. Next to yours configuration.nix file, create dancing-script/default.nix file:

{ lib, fetchFromGitHub }:

let
  pname = "dancing-script";
  version = "2.0";
in fetchFromGitHub {
  name = "${pname}-${version}";
  
  owner = "impallari";
  repo = "DancingScript";
  rev = "f7f54bc1b8836601dae8696666bfacd306f77e34";
  sha256 = "dfFvh8h+oMhAQL9XKMrNr07VUkdQdxAsA8+q27KWWCA=";

  postFetch = ''
    tar xf $downloadedFile --strip=1
    install -m444 -Dt $out/share/fonts/truetype fonts/ttf/*.ttf
  '';

  meta = with lib; {
    description = "Dancing Script";
    longDescription = "A lively casual script where the letters bounce and change size slightly.";
    homepage = "https://github.com/impallari/DancingScript";
    license = licenses.ofl;
    platforms = platforms.all;
    maintainers = with maintainers; [ wdavidw ];
  };
}

Once the GitHub repository is downloaded, we'll install everything .ttf files in $out/share/fonts/truetype folder.

Package declaration

Assuming we edit one configuration.nix file co-located with dancing-script folder we import the new package into fonts.fonts option list:

{ config, pkgs, ... }:

let
  dancing-script = import ./dancing-script/default.nix {    inherit lib;    fetchFromGitHub = pkgs.fetchFromGitHub;  };in {
  imports =
    [
      ./david-framework-hardware.nix
    ];
  
  fonts.enableFontDir = true;
  fonts.fonts = with pkgs; [
    dancing-script    dejavu_fonts
    inter
  ];
  
}

Note how we satisfy the package dependencies by injecting lib and fetchFromGitHub when you call import. A shorter and simpler approach is used callPackage:

{ config, pkgs, ... }:

let
  dancing-script = pkgs.callPackage ./dancing-script/default.nix {  };in {
  imports =
    [
      ./david-framework-hardware.nix
    ];
  
  fonts.enableFontDir = true;
  fonts.fonts = with pkgs; [
    dancing-script    dejavu_fonts
    inter
  ];
  
}

Running nixos-rebuild switch (or darwin-rebuild switch on macOS) loads the font into the system. On Linux, fc-list lists the fonts available in the system:

fc-list | grep dancing/nix/store/fm8y81bjhcy8p4cp32230xr78807x0ii-dancing-script-2.000/share/fonts/truetype/DancingScript-Bold.ttf: Dancing Script:style=Bold
/nix/store/fm8y81bjhcy8p4cp32230xr78807x0ii-dancing-script-2.000/share/fonts/truetype/DancingScript-Regular.ttf: Dancing Script:style=Regular

Package integration with nixpkgs

Now that our package is working, the next step is to share our work with the community.

Start by sharing the nixpkgs repository and cloning the fork on your machine:

git clone origin https://github.com/wdavidw/nixpkgs.git
cd nixpkgs

Insights on how to contribute to the project are entered CONTRIBUTING.md. Creating a merge request to propose a new package involves 3 commits:

  • create the package nix file
  • update pkgs/top-level/all-packages.nix to register the package
  • updates maintainers/maintainer-list.nix to register if you are not already present

Inside pkgs/data/fontscreate a new one dancing-script folder and import default.nix file found above.

Update all-packages.nix and maintainer-list.nix files too. Their content is self-explanatory. There is also some sort of order inside these two files, but it is not strictly enforced.

The former register our new package:

  
  dancing-script = callPackage ../data/fonts/dancing-script { };
  

When you later register as a contributor:

  
  wdavidw = {
    name = "David Worms";
    email = "david@adaltas.com";
    github = "wdavidw";
    githubId = 46896;
  };
  

Your githubId the value is exposed by the GitHub API at https://api.github.com/users/{username}replacing {username} with your GitHub handle.

The dancing-script the package is now registered in nixpkgs.

Testing packages from nixpkgs

Before submitting the pull request, it is possible to associate and test our Nix configuration with the local one nixpkgs the repository. Run it nixos-rebuild switch command (or darwin-rebuild switch on macOS) with the extra -I arguments to reconfigure the machine with the local nixpkgs packages including our latest addition.

First, we update and simplify our configuration.nix file accordingly:

{ config, pkgs, ... }:

{
  imports =
    [
      ./david-framework-hardware.nix
    ];
  
  
  fonts.enableFontDir = true;
  fonts.fonts = with pkgs; [
    dancing-script
    dejavu_fonts
    inter
  ];
  
}

From nixpkgs directory is the command to reconfigure the machine with the local nixpkgs repository:

nixos-rebuild switch -I nixpkgs=.

Package publishing

The process of sharing the changes with the community is standard GitOps.

Changes are made with:

git add \
  maintainers/maintainer-list.nix \
  pkgs/data/fonts/dancing-script/default.nix \
  pkgs/top-level/all-packages.nix
git commit -m 'dancing-script: init at 2.0'
git push origin master

The confirmation message respects the guidelines contained in CONTRIBUTING.md. Go to your GitHub repository and create the pull request.

Conclusion

The final result was published shortly before this article. The merge request is visible online as “PR #166057, dance scripts: init on 2.0”. It merges within 24 hours and I am now an official NixOS maintainer!

#Nix #package #creation #install #font #supported

Source link

Leave a Reply