···14141515 /* Return an attribute from nested attribute sets.
16161717+ Nix has an [attribute selection operator `. or`](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
1818+1919+ ```nix
2020+ (x.a.b or 6) == attrByPath ["a" "b"] 6 x
2121+ # and
2222+ (x.${f p}."example.com" or 6) == attrByPath [ (f p) "example.com" ] 6 x
2323+ ```
2424+1725 Example:
1826 x = { a = { b = 3; }; }
1927 # ["a" "b"] is equivalent to x.a.b
···5058 attrByPath' 0 set;
51595260 /* Return if an attribute from nested attribute set exists.
6161+6262+ Nix has a [has attribute operator `?`](https://nixos.org/manual/nix/stable/language/operators#has-attribute), which is sufficient for such queries, as long as the number of attributes is static. For example:
6363+6464+ ```nix
6565+ (x?a.b) == hasAttryByPath ["a" "b"] x
6666+ # and
6767+ (x?${f p}."example.com") == hasAttryByPath [ (f p) "example.com" ] x
6868+ ```
53695470 **Laws**:
5571 1. ```nix
···176192177193 /* Like `attrByPath`, but without a default value. If it doesn't find the
178194 path it will throw an error.
195195+196196+ Nix has an [attribute selection operator](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
197197+198198+ ```nix
199199+ x.a.b == getAttrByPath ["a" "b"] x
200200+ # and
201201+ x.${f p}."example.com" == getAttrByPath [ (f p) "example.com" ] x
202202+ ```
179203180204 Example:
181205 x = { a = { b = 3; }; }
+15-19
lib/meta.nix
···44{ lib }:
5566let
77- inherit (lib) matchAttrs any all;
88- inherit (builtins) isString;
77+ inherit (lib) matchAttrs any all isDerivation getBin assertMsg;
88+ inherit (builtins) isString match typeOf;
991010in
1111rec {
···154154 getExe pkgs.mustache-go
155155 => "/nix/store/am9ml4f4ywvivxnkiaqwr0hyxka1xjsf-mustache-go-1.3.0/bin/mustache"
156156 */
157157- getExe = x:
158158- let
159159- y = x.meta.mainProgram or (
160160- # This could be turned into an error when 23.05 is at end of life
161161- lib.warn "getExe: Package ${lib.strings.escapeNixIdentifier x.meta.name or x.pname or x.name} does not have the meta.mainProgram attribute. We'll assume that the main program has the same name for now, but this behavior is deprecated, because it leads to surprising errors when the assumption does not hold. If the package has a main program, please set `meta.mainProgram` in its definition to make this warning go away. Otherwise, if the package does not have a main program, or if you don't control its definition, use getExe' to specify the name to the program, such as lib.getExe' foo \"bar\"."
162162- lib.getName
163163- x
164164- );
165165- in
166166- getExe' x y;
157157+ getExe = x: getExe' x (x.meta.mainProgram or (
158158+ # This could be turned into an error when 23.05 is at end of life
159159+ lib.warn "getExe: Package ${lib.strings.escapeNixIdentifier x.meta.name or x.pname or x.name} does not have the meta.mainProgram attribute. We'll assume that the main program has the same name for now, but this behavior is deprecated, because it leads to surprising errors when the assumption does not hold. If the package has a main program, please set `meta.mainProgram` in its definition to make this warning go away. Otherwise, if the package does not have a main program, or if you don't control its definition, use getExe' to specify the name to the program, such as lib.getExe' foo \"bar\"."
160160+ lib.getName
161161+ x
162162+ ));
167163168164 /* Get the path of a program of a derivation.
169165···175171 => "/nix/store/5rs48jamq7k6sal98ymj9l4k2bnwq515-imagemagick-7.1.1-15/bin/convert"
176172 */
177173 getExe' = x: y:
178178- assert lib.assertMsg (lib.isDerivation x)
179179- "lib.meta.getExe': The first argument is of type ${builtins.typeOf x}, but it should be a derivation instead.";
180180- assert lib.assertMsg (lib.isString y)
181181- "lib.meta.getExe': The second argument is of type ${builtins.typeOf y}, but it should be a string instead.";
182182- assert lib.assertMsg (builtins.length (lib.splitString "/" y) == 1)
183183- "lib.meta.getExe': The second argument \"${y}\" is a nested path with a \"/\" character, but it should just be the name of the executable instead.";
184184- "${lib.getBin x}/bin/${y}";
174174+ assert assertMsg (isDerivation x)
175175+ "lib.meta.getExe': The first argument is of type ${typeOf x}, but it should be a derivation instead.";
176176+ assert assertMsg (isString y)
177177+ "lib.meta.getExe': The second argument is of type ${typeOf y}, but it should be a string instead.";
178178+ assert assertMsg (match ".*\/.*" y == null)
179179+ "lib.meta.getExe': The second argument \"${y}\" is a nested path with a \"/\" character, but it should just be the name of the executable instead.";
180180+ "${getBin x}/bin/${y}";
185181}
+81
lib/path/default.nix
···99 split
1010 match
1111 typeOf
1212+ storeDir
1213 ;
13141415 inherit (lib.lists)
···2324 take
2425 drop
2526 ;
2727+2828+ listHasPrefix = lib.lists.hasPrefix;
26292730 inherit (lib.strings)
2831 concatStringsSep
···119122 if base == dirOf base then { root = base; inherit components; }
120123 else recurse ([ (baseNameOf base) ] ++ components) (dirOf base);
121124 in recurse [];
125125+126126+ # The components of the store directory, typically [ "nix" "store" ]
127127+ storeDirComponents = splitRelPath ("./" + storeDir);
128128+ # The number of store directory components, typically 2
129129+ storeDirLength = length storeDirComponents;
130130+131131+ # Type: [ String ] -> Bool
132132+ #
133133+ # Whether path components have a store path as a prefix, according to
134134+ # https://nixos.org/manual/nix/stable/store/store-path.html#store-path.
135135+ componentsHaveStorePathPrefix = components:
136136+ # path starts with the store directory (typically /nix/store)
137137+ listHasPrefix storeDirComponents components
138138+ # is not the store directory itself, meaning there's at least one extra component
139139+ && storeDirComponents != components
140140+ # and the first component after the store directory has the expected format.
141141+ # NOTE: We could change the hash regex to be [0-9a-df-np-sv-z],
142142+ # because these are the actual ASCII characters used by Nix's base32 implementation,
143143+ # but this is not fully specified, so let's tie this too much to the currently implemented concept of store paths.
144144+ # Similar reasoning applies to the validity of the name part.
145145+ # We care more about discerning store path-ness on realistic values. Making it airtight would be fragile and slow.
146146+ && match ".{32}-.+" (elemAt components storeDirLength) != null;
122147123148in /* No rec! Add dependencies on this file at the top. */ {
124149···320345 root = deconstructed.root;
321346 subpath = joinRelPath deconstructed.components;
322347 };
348348+349349+ /*
350350+ Whether a [path](https://nixos.org/manual/nix/stable/language/values.html#type-path)
351351+ has a [store path](https://nixos.org/manual/nix/stable/store/store-path.html#store-path)
352352+ as a prefix.
353353+354354+ :::{.note}
355355+ As with all functions of this `lib.path` library, it does not work on paths in strings,
356356+ which is how you'd typically get store paths.
357357+358358+ Instead, this function only handles path values themselves,
359359+ which occur when Nix files in the store use relative path expressions.
360360+ :::
361361+362362+ Type:
363363+ hasStorePathPrefix :: Path -> Bool
364364+365365+ Example:
366366+ # Subpaths of derivation outputs have a store path as a prefix
367367+ hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo/bar/baz
368368+ => true
369369+370370+ # The store directory itself is not a store path
371371+ hasStorePathPrefix /nix/store
372372+ => false
373373+374374+ # Derivation outputs are store paths themselves
375375+ hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo
376376+ => true
377377+378378+ # Paths outside the Nix store don't have a store path prefix
379379+ hasStorePathPrefix /home/user
380380+ => false
381381+382382+ # Not all paths under the Nix store are store paths
383383+ hasStorePathPrefix /nix/store/.links/10gg8k3rmbw8p7gszarbk7qyd9jwxhcfq9i6s5i0qikx8alkk4hq
384384+ => false
385385+386386+ # Store derivations are also store paths themselves
387387+ hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo.drv
388388+ => true
389389+ */
390390+ hasStorePathPrefix = path:
391391+ let
392392+ deconstructed = deconstructPath path;
393393+ in
394394+ assert assertMsg
395395+ (isPath path)
396396+ "lib.path.hasStorePathPrefix: Argument is of type ${typeOf path}, but a path was expected";
397397+ assert assertMsg
398398+ # This function likely breaks or needs adjustment if used with other filesystem roots, if they ever get implemented.
399399+ # Let's try to error nicely in such a case, though it's unclear how an implementation would work even and whether this could be detected.
400400+ # See also https://github.com/NixOS/nix/pull/6530#discussion_r1422843117
401401+ (deconstructed.root == /. && toString deconstructed.root == "/")
402402+ "lib.path.hasStorePathPrefix: Argument has a filesystem root (${toString deconstructed.root}) that's not /, which is currently not supported.";
403403+ componentsHaveStorePathPrefix deconstructed.components;
323404324405 /*
325406 Whether a value is a valid subpath string.
···8989 # is why we use the more obscure "bfd" and not "binutils" for this
9090 # choice.
9191 else "bfd";
9292+ # The standard lib directory name that non-nixpkgs binaries distributed
9393+ # for this platform normally assume.
9494+ libDir = if final.isLinux then
9595+ if final.isx86_64 || final.isMips64 || final.isPower64
9696+ then "lib64"
9797+ else "lib"
9898+ else null;
9299 extensions = lib.optionalAttrs final.hasSharedLibraries {
93100 sharedLibrary =
94101 if final.isDarwin then ".dylib"
+4
nixos/doc/manual/release-notes/rl-2405.section.md
···10101111- `screen`'s module has been cleaned, and will now require you to set `programs.screen.enable` in order to populate `screenrc` and add the program to the environment.
12121313+- NixOS now installs a stub ELF loader that prints an informative error message when users attempt to run binaries not made for NixOS.
1414+ - This can be disabled through the `environment.stub-ld.enable` option.
1515+ - If you use `programs.nix-ld.enable`, no changes are needed. The stub will be disabled automatically.
1616+1317## New Services {#sec-release-24.05-new-services}
14181519<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+58
nixos/modules/config/ldso.nix
···11+{ config, lib, pkgs, ... }:
22+33+let
44+ inherit (lib) last splitString mkOption types mdDoc optionals;
55+66+ libDir = pkgs.stdenv.hostPlatform.libDir;
77+ ldsoBasename = last (splitString "/" pkgs.stdenv.cc.bintools.dynamicLinker);
88+99+ pkgs32 = pkgs.pkgsi686Linux;
1010+ libDir32 = pkgs32.stdenv.hostPlatform.libDir;
1111+ ldsoBasename32 = last (splitString "/" pkgs32.stdenv.cc.bintools.dynamicLinker);
1212+in {
1313+ options = {
1414+ environment.ldso = mkOption {
1515+ type = types.nullOr types.path;
1616+ default = null;
1717+ description = mdDoc ''
1818+ The executable to link into the normal FHS location of the ELF loader.
1919+ '';
2020+ };
2121+2222+ environment.ldso32 = mkOption {
2323+ type = types.nullOr types.path;
2424+ default = null;
2525+ description = mdDoc ''
2626+ The executable to link into the normal FHS location of the 32-bit ELF loader.
2727+2828+ This currently only works on x86_64 architectures.
2929+ '';
3030+ };
3131+ };
3232+3333+ config = {
3434+ assertions = [
3535+ { assertion = isNull config.environment.ldso32 || pkgs.stdenv.isx86_64;
3636+ message = "Option environment.ldso32 currently only works on x86_64.";
3737+ }
3838+ ];
3939+4040+ systemd.tmpfiles.rules = (
4141+ if isNull config.environment.ldso then [
4242+ "r /${libDir}/${ldsoBasename} - - - - -"
4343+ ] else [
4444+ "d /${libDir} 0755 root root - -"
4545+ "L+ /${libDir}/${ldsoBasename} - - - - ${config.environment.ldso}"
4646+ ]
4747+ ) ++ optionals pkgs.stdenv.isx86_64 (
4848+ if isNull config.environment.ldso32 then [
4949+ "r /${libDir32}/${ldsoBasename32} - - - - -"
5050+ ] else [
5151+ "d /${libDir32} 0755 root root - -"
5252+ "L+ /${libDir32}/${ldsoBasename32} - - - - ${config.environment.ldso32}"
5353+ ]
5454+ );
5555+ };
5656+5757+ meta.maintainers = with lib.maintainers; [ tejing ];
5858+}
+56
nixos/modules/config/stub-ld.nix
···11+{ config, lib, pkgs, ... }:
22+33+let
44+ inherit (lib) optionalString mkOption types mdDoc mkIf mkDefault;
55+66+ cfg = config.environment.stub-ld;
77+88+ message = ''
99+ NixOS cannot run dynamically linked executables intended for generic
1010+ linux environments out of the box. For more information, see:
1111+ https://nix.dev/permalink/stub-ld
1212+ '';
1313+1414+ stub-ld-for = pkgsArg: messageArg: pkgsArg.pkgsStatic.runCommandCC "stub-ld" {
1515+ nativeBuildInputs = [ pkgsArg.unixtools.xxd ];
1616+ inherit messageArg;
1717+ } ''
1818+ printf "%s" "$messageArg" | xxd -i -n message >main.c
1919+ cat <<EOF >>main.c
2020+ #include <stdio.h>
2121+ int main(int argc, char * argv[]) {
2222+ fprintf(stderr, "Could not start dynamically linked executable: %s\n", argv[0]);
2323+ fwrite(message, sizeof(unsigned char), message_len, stderr);
2424+ return 127; // matches behavior of bash and zsh without a loader. fish uses 139
2525+ }
2626+ EOF
2727+ $CC -Os main.c -o $out
2828+ '';
2929+3030+ pkgs32 = pkgs.pkgsi686Linux;
3131+3232+ stub-ld = stub-ld-for pkgs message;
3333+ stub-ld32 = stub-ld-for pkgs32 message;
3434+in {
3535+ options = {
3636+ environment.stub-ld = {
3737+ enable = mkOption {
3838+ type = types.bool;
3939+ default = true;
4040+ example = false;
4141+ description = mdDoc ''
4242+ Install a stub ELF loader to print an informative error message
4343+ in the event that a user attempts to run an ELF binary not
4444+ compiled for NixOS.
4545+ '';
4646+ };
4747+ };
4848+ };
4949+5050+ config = mkIf cfg.enable {
5151+ environment.ldso = mkDefault stub-ld;
5252+ environment.ldso32 = mkIf pkgs.stdenv.isx86_64 (mkDefault stub-ld32);
5353+ };
5454+5555+ meta.maintainers = with lib.maintainers; [ tejing ];
5656+}
···14351435 remote_timeout = mkOpt types.str ''
14361436 Timeout for requests to the remote write endpoint.
14371437 '';
14381438+ headers = mkOpt (types.attrsOf types.str) ''
14391439+ Custom HTTP headers to be sent along with each remote write request.
14401440+ Be aware that headers that are set by Prometheus itself can't be overwritten.
14411441+ '';
14381442 write_relabel_configs = mkOpt (types.listOf promTypes.relabel_config) ''
14391443 List of remote write relabel configurations.
14401444 '';
···15291533 '';
15301534 remote_timeout = mkOpt types.str ''
15311535 Timeout for requests to the remote read endpoint.
15361536+ '';
15371537+ headers = mkOpt (types.attrsOf types.str) ''
15381538+ Custom HTTP headers to be sent along with each remote read request.
15391539+ Be aware that headers that are set by Prometheus itself can't be overwritten.
15321540 '';
15331541 read_recent = mkOpt types.bool ''
15341542 Whether reads should be made for queries for time ranges that
···2020 , extraScripts ? []
2121 , ... }@args:
2222 let
2323+ strippedName = with builtins;
2424+ let groups = match "mpv[-_](.*)" pname; in
2525+ if groups != null
2626+ then head groups
2727+ else pname
2828+ ;
2329 # either passthru.scriptName, inferred from scriptPath, or from pname
2430 scriptName = (args.passthru or {}).scriptName or (
2531 if args ? scriptPath
2632 then fileName args.scriptPath
2727- else "${pname}.lua"
3333+ else "${strippedName}.lua"
2834 );
2935 scriptPath = args.scriptPath or "./${scriptName}";
3036 in {
···49495050 nativeImageBuildArgs = nativeImageBuildArgs ++ extraNativeImageBuildArgs ++ [ graalvmXmx ];
51515252+ # Workaround GraalVM issue where the builder does not have access to the
5353+ # environment variables since 21.0.0
5454+ # https://github.com/oracle/graal/pull/6095
5555+ # https://github.com/oracle/graal/pull/6095
5656+ # https://github.com/oracle/graal/issues/7502
5757+ env.NATIVE_IMAGE_DEPRECATED_BUILDER_SANITATION = "true";
5858+5259 buildPhase = args.buildPhase or ''
5360 runHook preBuild
5461
+49
pkgs/by-name/no/noto-fonts-cjk-sans/package.nix
···11+{ lib
22+, stdenvNoCC
33+, fetchFromGitHub
44+, nixosTests
55+, gitUpdater
66+}:
77+88+stdenvNoCC.mkDerivation rec {
99+ pname = "noto-fonts-cjk-sans";
1010+ version = "2.004";
1111+1212+ src = fetchFromGitHub {
1313+ owner = "notofonts";
1414+ repo = "noto-cjk";
1515+ rev = "Sans${version}";
1616+ hash = "sha256-IgalJkiOAVjNxKaPAQWfb5hKeqclliR4qVXCq63FGWY=";
1717+ sparseCheckout = [ "Sans/Variable/OTC" ];
1818+ };
1919+2020+ installPhase = ''
2121+ install -m444 -Dt $out/share/fonts/opentype/noto-cjk Sans/Variable/OTC/*.otf.ttc
2222+ '';
2323+2424+ passthru.tests.noto-fonts = nixosTests.noto-fonts;
2525+2626+ passthru.updateScript = gitUpdater {
2727+ rev-prefix = "Sans";
2828+ };
2929+3030+ meta = {
3131+ description = "Beautiful and free fonts for CJK languages";
3232+ homepage = "https://www.google.com/get/noto/help/cjk/";
3333+ longDescription = ''
3434+ Noto Sans CJK is a sans typeface designed as
3535+ an intermediate style between the modern and traditional. It is
3636+ intended to be a multi-purpose digital font for user interface
3737+ designs, digital content, reading on laptops, mobile devices, and
3838+ electronic books. Noto Sans CJK comprehensively covers
3939+ Simplified Chinese, Traditional Chinese, Japanese, and Korean in a
4040+ unified font family. It supports regional variants of ideographic
4141+ characters for each of the four languages. In addition, it supports
4242+ Japanese kana, vertical forms, and variant characters (itaiji); it
4343+ supports Korean hangeul — both contemporary and archaic.
4444+ '';
4545+ license = lib.licenses.ofl;
4646+ platforms = lib.platforms.all;
4747+ maintainers = with lib.maintainers; [ mathnerd314 emily ];
4848+ };
4949+}
+49
pkgs/by-name/no/noto-fonts-cjk-serif/package.nix
···11+{ lib
22+, stdenvNoCC
33+, fetchFromGitHub
44+, nixosTests
55+, gitUpdater
66+}:
77+88+stdenvNoCC.mkDerivation rec {
99+ pname = "noto-fonts-cjk-serif";
1010+ version = "2.002";
1111+1212+ src = fetchFromGitHub {
1313+ owner = "notofonts";
1414+ repo = "noto-cjk";
1515+ rev = "Serif${version}";
1616+ hash = "sha256-GLjpTAiHfygj1J4AdUVDJh8kykkFOglq+h4kyat5W9s=";
1717+ sparseCheckout = [ "Serif/Variable/OTC" ];
1818+ };
1919+2020+ installPhase = ''
2121+ install -m444 -Dt $out/share/fonts/opentype/noto-cjk Serif/Variable/OTC/*.otf.ttc
2222+ '';
2323+2424+ passthru.tests.noto-fonts = nixosTests.noto-fonts;
2525+2626+ passthru.updateScript = gitUpdater {
2727+ rev-prefix = "Serif";
2828+ };
2929+3030+ meta = with lib; {
3131+ description = "Beautiful and free fonts for CJK languages";
3232+ homepage = "https://www.google.com/get/noto/help/cjk/";
3333+ longDescription = ''
3434+ Noto Serif CJK is a serif typeface designed as
3535+ an intermediate style between the modern and traditional. It is
3636+ intended to be a multi-purpose digital font for user interface
3737+ designs, digital content, reading on laptops, mobile devices, and
3838+ electronic books. Noto Serif CJK comprehensively covers
3939+ Simplified Chinese, Traditional Chinese, Japanese, and Korean in a
4040+ unified font family. It supports regional variants of ideographic
4141+ characters for each of the four languages. In addition, it supports
4242+ Japanese kana, vertical forms, and variant characters (itaiji); it
4343+ supports Korean hangeul — both contemporary and archaic.
4444+ '';
4545+ license = licenses.ofl;
4646+ platforms = platforms.all;
4747+ maintainers = with maintainers; [ mathnerd314 emily ];
4848+ };
4949+}
···11+{ lib
22+, stdenvNoCC
33+, fetchFromGitHub
44+, gitUpdater
55+, variants ? [ ]
66+, suffix ? ""
77+, longDescription ? ''
88+ When text is rendered by a computer, sometimes characters are
99+ displayed as “tofu”. They are little boxes to indicate your device
1010+ doesn’t have a font to display the text.
1111+ Google has been developing a font family called Noto, which aims to
1212+ support all languages with a harmonious look and feel. Noto is
1313+ Google’s answer to tofu. The name noto is to convey the idea that
1414+ Google’s goal is to see “no more tofu”. Noto has multiple styles and
1515+ weights, and freely available to all.
1616+ ''
1717+}:
1818+1919+stdenvNoCC.mkDerivation rec {
2020+ pname = "noto-fonts${suffix}";
2121+ version = "23.11.1";
2222+2323+ src = fetchFromGitHub {
2424+ owner = "notofonts";
2525+ repo = "notofonts.github.io";
2626+ rev = "noto-monthly-release-${version}";
2727+ hash = "sha256-qBHLCOfVBOn9CV194S4cYw9nhHyAe2AUBJHQMvyEfW8=";
2828+ };
2929+3030+ _variants = map (variant: builtins.replaceStrings [ " " ] [ "" ] variant) variants;
3131+3232+ installPhase = ''
3333+ # We check availability in order of variable -> otf -> ttf
3434+ # unhinted -- the hinted versions use autohint
3535+ # maintaining maximum coverage.
3636+ #
3737+ # We have a mix of otf and ttf fonts
3838+ local out_font=$out/share/fonts/noto
3939+ '' + (if _variants == [ ] then ''
4040+ for folder in $(ls -d fonts/*/); do
4141+ if [[ -d "$folder"unhinted/variable-ttf ]]; then
4242+ install -m444 -Dt $out_font "$folder"unhinted/variable-ttf/*.ttf
4343+ elif [[ -d "$folder"unhinted/otf ]]; then
4444+ install -m444 -Dt $out_font "$folder"unhinted/otf/*.otf
4545+ else
4646+ install -m444 -Dt $out_font "$folder"unhinted/ttf/*.ttf
4747+ fi
4848+ done
4949+ '' else ''
5050+ for variant in $_variants; do
5151+ if [[ -d fonts/"$variant"/unhinted/variable-ttf ]]; then
5252+ install -m444 -Dt $out_font fonts/"$variant"/unhinted/variable-ttf/*.ttf
5353+ elif [[ -d fonts/"$variant"/unhinted/otf ]]; then
5454+ install -m444 -Dt $out_font fonts/"$variant"/unhinted/otf/*.otf
5555+ else
5656+ install -m444 -Dt $out_font fonts/"$variant"/unhinted/ttf/*.ttf
5757+ fi
5858+ done
5959+ '');
6060+6161+ passthru.updateScript = gitUpdater {
6262+ rev-prefix = "noto-monthly-release-";
6363+ };
6464+6565+ meta = {
6666+ description = "Beautiful and free fonts for many languages";
6767+ homepage = "https://www.google.com/get/noto/";
6868+ inherit longDescription;
6969+ license = lib.licenses.ofl;
7070+ platforms = lib.platforms.all;
7171+ maintainers = with lib.maintainers; [ mathnerd314 emily jopejoe1 ];
7272+ };
7373+}
-305
pkgs/data/fonts/noto-fonts/default.nix
···11-{ stdenv
22-, stdenvNoCC
33-, lib
44-, gitUpdater
55-, fetchFromGitHub
66-, fetchurl
77-, cairo
88-, nixosTests
99-, pkg-config
1010-, pngquant
1111-, which
1212-, imagemagick
1313-, zopfli
1414-, buildPackages
1515-, variants ? [ ]
1616-}:
1717-let
1818- notoLongDescription = ''
1919- When text is rendered by a computer, sometimes characters are
2020- displayed as “tofu”. They are little boxes to indicate your device
2121- doesn’t have a font to display the text.
2222-2323- Google has been developing a font family called Noto, which aims to
2424- support all languages with a harmonious look and feel. Noto is
2525- Google’s answer to tofu. The name noto is to convey the idea that
2626- Google’s goal is to see “no more tofu”. Noto has multiple styles and
2727- weights, and freely available to all.
2828- '';
2929-in
3030-rec {
3131- mkNoto =
3232- { pname
3333- , variants ? [ ]
3434- , longDescription ? notoLongDescription
3535- }:
3636- stdenvNoCC.mkDerivation rec {
3737- inherit pname;
3838- version = "23.11.1";
3939-4040- src = fetchFromGitHub {
4141- owner = "notofonts";
4242- repo = "notofonts.github.io";
4343- rev = "noto-monthly-release-${version}";
4444- hash = "sha256-qBHLCOfVBOn9CV194S4cYw9nhHyAe2AUBJHQMvyEfW8=";
4545- };
4646-4747- _variants = map (variant: builtins.replaceStrings [ " " ] [ "" ] variant) variants;
4848-4949- installPhase = ''
5050- # We check availability in order of variable -> otf -> ttf
5151- # unhinted -- the hinted versions use autohint
5252- # maintaining maximum coverage.
5353- #
5454- # We have a mix of otf and ttf fonts
5555- local out_font=$out/share/fonts/noto
5656- '' + (if _variants == [ ] then ''
5757- for folder in $(ls -d fonts/*/); do
5858- if [[ -d "$folder"unhinted/variable-ttf ]]; then
5959- install -m444 -Dt $out_font "$folder"unhinted/variable-ttf/*.ttf
6060- elif [[ -d "$folder"unhinted/otf ]]; then
6161- install -m444 -Dt $out_font "$folder"unhinted/otf/*.otf
6262- else
6363- install -m444 -Dt $out_font "$folder"unhinted/ttf/*.ttf
6464- fi
6565- done
6666- '' else ''
6767- for variant in $_variants; do
6868- if [[ -d fonts/"$variant"/unhinted/variable-ttf ]]; then
6969- install -m444 -Dt $out_font fonts/"$variant"/unhinted/variable-ttf/*.ttf
7070- elif [[ -d fonts/"$variant"/unhinted/otf ]]; then
7171- install -m444 -Dt $out_font fonts/"$variant"/unhinted/otf/*.otf
7272- else
7373- install -m444 -Dt $out_font fonts/"$variant"/unhinted/ttf/*.ttf
7474- fi
7575- done
7676- '');
7777-7878- passthru.updateScript = gitUpdater {
7979- rev-prefix = "noto-monthly-release-";
8080- };
8181-8282- meta = with lib; {
8383- description = "Beautiful and free fonts for many languages";
8484- homepage = "https://www.google.com/get/noto/";
8585- inherit longDescription;
8686- license = licenses.ofl;
8787- platforms = platforms.all;
8888- maintainers = with maintainers; [ mathnerd314 emily jopejoe1 ];
8989- };
9090- };
9191-9292- mkNotoCJK = { typeface, version, sha256 }:
9393- stdenvNoCC.mkDerivation {
9494- pname = "noto-fonts-cjk-${lib.toLower typeface}";
9595- inherit version;
9696-9797- src = fetchFromGitHub {
9898- owner = "googlefonts";
9999- repo = "noto-cjk";
100100- rev = "${typeface}${version}";
101101- inherit sha256;
102102- sparseCheckout = [ "${typeface}/Variable/OTC" ];
103103- };
104104-105105- installPhase = ''
106106- install -m444 -Dt $out/share/fonts/opentype/noto-cjk ${typeface}/Variable/OTC/*.otf.ttc
107107- '';
108108-109109- passthru.tests.noto-fonts = nixosTests.noto-fonts;
110110-111111- meta = with lib; {
112112- description = "Beautiful and free fonts for CJK languages";
113113- homepage = "https://www.google.com/get/noto/help/cjk/";
114114- longDescription = ''
115115- Noto ${typeface} CJK is a ${lib.toLower typeface} typeface designed as
116116- an intermediate style between the modern and traditional. It is
117117- intended to be a multi-purpose digital font for user interface
118118- designs, digital content, reading on laptops, mobile devices, and
119119- electronic books. Noto ${typeface} CJK comprehensively covers
120120- Simplified Chinese, Traditional Chinese, Japanese, and Korean in a
121121- unified font family. It supports regional variants of ideographic
122122- characters for each of the four languages. In addition, it supports
123123- Japanese kana, vertical forms, and variant characters (itaiji); it
124124- supports Korean hangeul — both contemporary and archaic.
125125- '';
126126- license = licenses.ofl;
127127- platforms = platforms.all;
128128- maintainers = with maintainers; [ mathnerd314 emily ];
129129- };
130130- };
131131-132132- noto-fonts = mkNoto {
133133- pname = "noto-fonts";
134134- };
135135-136136- noto-fonts-lgc-plus = mkNoto {
137137- pname = "noto-fonts-lgc-plus";
138138- variants = [
139139- "Noto Sans"
140140- "Noto Serif"
141141- "Noto Sans Mono"
142142- "Noto Music"
143143- "Noto Sans Symbols"
144144- "Noto Sans Symbols 2"
145145- "Noto Sans Math"
146146- ];
147147- longDescription = ''
148148- This package provides the Noto Fonts, but only for latin, greek
149149- and cyrillic scripts, as well as some extra fonts. To create a
150150- custom Noto package with custom variants, see the `mkNoto`
151151- helper function.
152152- '';
153153- };
154154-155155- noto-fonts-cjk-sans = mkNotoCJK {
156156- typeface = "Sans";
157157- version = "2.004";
158158- sha256 = "sha256-IgalJkiOAVjNxKaPAQWfb5hKeqclliR4qVXCq63FGWY=";
159159- };
160160-161161- noto-fonts-cjk-serif = mkNotoCJK {
162162- typeface = "Serif";
163163- version = "2.002";
164164- sha256 = "sha256-GLjpTAiHfygj1J4AdUVDJh8kykkFOglq+h4kyat5W9s=";
165165- };
166166-167167- noto-fonts-color-emoji =
168168- let
169169- version = "2.042";
170170- emojiPythonEnv =
171171- buildPackages.python3.withPackages (p: with p; [ fonttools nototools ]);
172172- in
173173- stdenvNoCC.mkDerivation {
174174- pname = "noto-fonts-emoji";
175175- inherit version;
176176-177177- src = fetchFromGitHub {
178178- owner = "googlefonts";
179179- repo = "noto-emoji";
180180- rev = "v${version}";
181181- hash = "sha256-otJQMXrBIPrxD1vCdgcrZ2h1a9XAMbqEBFumjz1XJ54=";
182182- };
183183-184184- depsBuildBuild = [
185185- buildPackages.stdenv.cc
186186- pkg-config
187187- cairo
188188- ];
189189-190190- nativeBuildInputs = [
191191- imagemagick
192192- zopfli
193193- pngquant
194194- which
195195- emojiPythonEnv
196196- ];
197197-198198- postPatch = ''
199199- patchShebangs *.py
200200- patchShebangs third_party/color_emoji/*.py
201201- # remove check for virtualenv, since we handle
202202- # python requirements using python.withPackages
203203- sed -i '/ifndef VIRTUAL_ENV/,+2d' Makefile
204204-205205- # Make the build verbose so it won't get culled by Hydra thinking that
206206- # it somehow got stuck doing nothing.
207207- sed -i 's;\t@;\t;' Makefile
208208- '';
209209-210210- enableParallelBuilding = true;
211211-212212- installPhase = ''
213213- runHook preInstall
214214- mkdir -p $out/share/fonts/noto
215215- cp NotoColorEmoji.ttf $out/share/fonts/noto
216216- runHook postInstall
217217- '';
218218-219219- meta = with lib; {
220220- description = "Color emoji font";
221221- homepage = "https://github.com/googlefonts/noto-emoji";
222222- license = with licenses; [ ofl asl20 ];
223223- platforms = platforms.all;
224224- maintainers = with maintainers; [ mathnerd314 sternenseemann ];
225225- };
226226- };
227227-228228- noto-fonts-monochrome-emoji =
229229- # Metadata fetched from
230230- # https://www.googleapis.com/webfonts/v1/webfonts?key=${GOOGLE_FONTS_TOKEN}&family=Noto+Emoji
231231- let metadata = with builtins; head (fromJSON (readFile ./noto-emoji.json)).items;
232232- urlHashes = with builtins; fromJSON (readFile ./noto-emoji.hashes.json);
233233-234234- in
235235- stdenvNoCC.mkDerivation {
236236- pname = "noto-fonts-monochrome-emoji";
237237- version = "${lib.removePrefix "v" metadata.version}.${metadata.lastModified}";
238238- preferLocalBuild = true;
239239-240240- dontUnpack = true;
241241- srcs = let
242242- weightNames = {
243243- "300" = "Light";
244244- regular = "Regular";
245245- "500" = "Medium";
246246- "600" = "SemiBold";
247247- "700" = "Bold";
248248- };
249249- in lib.mapAttrsToList
250250- (variant: url: fetchurl { name = "NotoEmoji-${weightNames.${variant}}.ttf";
251251- hash = urlHashes.${url};
252252- inherit url; } )
253253- metadata.files;
254254-255255- installPhase = ''
256256- runHook preInstall
257257- for src in $srcs; do
258258- install -D $src $out/share/fonts/noto/$(stripHash $src)
259259- done
260260- runHook postInstall
261261- '';
262262-263263- meta = with lib; {
264264- description = "Monochrome emoji font";
265265- homepage = "https://fonts.google.com/noto/specimen/Noto+Emoji";
266266- license = [ licenses.ofl ];
267267- maintainers = [ maintainers.nicoo ];
268268-269269- platforms = platforms.all;
270270- sourceProvenance = [ sourceTypes.binaryBytecode ];
271271- };
272272- };
273273-274274- noto-fonts-emoji-blob-bin =
275275- let
276276- pname = "noto-fonts-emoji-blob-bin";
277277- version = "15.0";
278278- in
279279- stdenvNoCC.mkDerivation {
280280- inherit pname version;
281281-282282- src = fetchurl {
283283- url = "https://github.com/C1710/blobmoji/releases/download/v${version}/Blobmoji.ttf";
284284- hash = "sha256-3MPWZ1A2ups171dNIiFTJ3C1vZiGy6I8ZF70aUfrePk=";
285285- };
286286-287287- dontUnpack = true;
288288-289289- installPhase = ''
290290- runHook preInstall
291291-292292- install -Dm 444 $src $out/share/fonts/blobmoji/Blobmoji.ttf
293293-294294- runHook postInstall
295295- '';
296296-297297- meta = with lib; {
298298- description = "Noto Emoji with extended Blob support";
299299- homepage = "https://github.com/C1710/blobmoji";
300300- license = with licenses; [ ofl asl20 ];
301301- platforms = platforms.all;
302302- maintainers = with maintainers; [ rileyinman jk ];
303303- };
304304- };
305305-}
···189189 ''
190190 # Move the outputs into their respective outputs.
191191 + strings.concatMapStringsSep "\n" mkMoveToOutputCommand (builtins.tail finalAttrs.outputs)
192192+ # Add a newline to the end of the installPhase, so that the post-install hook doesn't
193193+ # get concatenated with the last moveToOutput command.
194194+ + "\n"
192195 # Post-install hook
193196 + ''
194197 runHook postInstall