cabal2nix-2.21.2: src/Distribution/Nixpkgs/Haskell/FromCabal/Name.hs
{-# LANGUAGE OverloadedStrings #-}
module Distribution.Nixpkgs.Haskell.FromCabal.Name ( toNixName, libNixName, buildToolNixName ) where
import Data.Maybe
import Data.String
import Distribution.Package
import Distribution.Text
import Language.Nix
-- | Map Cabal names to Nix identifiers that don't need to be quoted.
--
-- Currently this only supports 'PackageName's that consist of nothing but ASCII
-- characters (as needs to be the case with all Hackage packages).
-- Cabal package names are not changed if they already are a Nix identifier
-- that doesn't need quoting (with some notable exceptions). If they would need
-- quoting, they are prefixed with an underscore.
--
-- >>> toNixName $ mkPackageName "cabal2nix"
-- Identifier "cabal2nix"
-- >>> toNixName $ mkPackageName "4Blocks"
-- Identifier "_4Blocks"
-- >>> toNixName $ mkPackageName "assert"
-- Identifier "_assert"
--
-- Package names that clash with attribute names that have a special meaning
-- to the Nix evaluator are also prefixed (e.g.
-- [@type@ is evaluated eagerly]((https://github.com/NixOS/cabal2nix/issues/163)).
--
-- The mapping is intended to be reversible, but this isn't implemented by
-- @cabal2nix@ yet (and untested). It also should not be considered
-- stable yet, in particular the following may be changed:
--
-- - Future versions of @cabal2nix@ may prefix more 'PackageName's.
-- - The mapping may be extended to support all possible 'PackageName's.
--
-- See also:
--
-- - [Cabal documentation on the package name field](https://cabal.readthedocs.io/en/stable/cabal-package-description-file.html#pkg-field-name)
-- - "Language.Nix.Identifier"
-- - [Nix documentation on identifiers](https://nix.dev/manual/nix/2.30/language/identifiers.html#identifier)
toNixName :: PackageName -> Identifier
toNixName n = fromString $
case unPackageName n of
"" -> error "toNixName: BUG: received empty package name"
'_':_ -> error "toNixName: BUG: PackageName starts with an underscore, but shouldn't"
name
-- From the Cabal documentation:
--
-- A valid package name comprises an alphanumeric ‘word’; or two or more
-- such words separated by a hyphen character (-). A word cannot be
-- comprised only of the digits 0 to 9.
--
-- Cabal also latin unicode characters while Hackage enforces that package
-- names are ASCII.
--
-- If the package name comes from Hackage, the set of legal characters
-- ([a-zA-Z0-9-]) is a subset of those permissible as a Nix identifier
-- without quoting ([a-zA-Z0-9_'-]). The main difference are the rules
-- governing what may go where. In the following cases a Hackage package
-- name is not a simple identifier and 'needsQuoting' returns True:
--
-- - if the first “word” of the package name starts with a number, e.g. 4Blocks.
-- - if the package name is the same one of the 'nixKeywords'.
--
-- If we prefix these strings with an underscore, they no longer need quoting.
-- Because Cabal 'PackageName's may not contain underscores this mapped name
-- can never clash. (Reversing the mapping is very simple at the moment as
-- a result.)
--
-- We additionally prefix perfectly usable identifiers like type and
-- recurseForDerivations if they have special meaning to the Nix evaluator
-- (or Hydra etc.) since it may cause evaluation failures if we expose a
-- package under haskellPackages instead of whatever value(s) Nix may
-- expect.
--
-- TODO: Add mapping for non-ASCII 'PackageName's, using __ prefix (?)
| needsQuoting name || name `elem` haveSpecialSemantics -> '_':name
| otherwise -> name
where
-- Special attributes that affect the behavior of the Nix evaluator in some way.
-- See https://github.com/NixOS/cabal2nix/issues/163.
-- We can ignore underscore prefixed attrs like __toString, __functor.
-- Only type is the name of a real package at the moment.
haveSpecialSemantics = [ "type", "outPath", "recurseForDerivations" ]
-- | Map library names specified in Cabal files to Nix package identifiers.
--
-- TODO: This list should not be hard-coded here; it belongs into the Nixpkgs
-- repository.
--
-- TODO: Re-use hook matching system from PostProcess.hs here.
libNixName :: String -> [Identifier]
libNixName "" = []
libNixName "adns" = return "adns"
libNixName "alsa" = return "alsa-lib"
libNixName "alut" = return "freealut"
libNixName "appindicator-0.1" = return "libappindicator-gtk2"
libNixName "appindicator3-0.1" = return "libappindicator-gtk3"
libNixName "asound" = return "alsa-lib"
libNixName "ayatana-appindicator3-0.1" = return "libayatana-appindicator"
libNixName "b2" = return "libb2"
libNixName "boost_context" = return "boost"
libNixName "bz2" = return "bzip2"
libNixName "c++" = [] -- What is that?
libNixName "cairo-gobject" = return "cairo"
libNixName "cairo-pdf" = return "cairo"
libNixName "cairo-ps" = return "cairo"
libNixName "cairo-svg" = return "cairo"
libNixName "clang" = return "libclang"
libNixName "clang-3.8" = return "libclang" -- TODO: guessNixIdentifier before libNixName…
libNixName "crypt" = return "libxcrypt" -- starting with NixOS 22.11, glibc's libcrypt will no longer be built
libNixName "crypto" = return "openssl"
libNixName "curses" = return "ncurses"
libNixName "dbusmenu-glib-0.4" = return "libdbusmenu"
libNixName "dbusmenu-gtk3-0.4" = ["libdbusmenu-gtk3", "gtk3"]
libNixName "dl" = [] -- provided by glibc
libNixName "ff" = return "libff"
libNixName "fftw3" = return "fftw"
libNixName "fftw3f" = return "fftwFloat"
libNixName "FLAC" = return "flac"
libNixName "freetype2" = return "freetype"
libNixName "gconf" = return "GConf"
libNixName "gconf-2.0" = return "GConf"
libNixName "gdk-2.0" = return "gtk2"
libNixName "gdk-3.0" = return "gtk3"
libNixName "gdk-pixbuf-2.0" = return "gdk-pixbuf"
libNixName "gdk-x11-2.0" = return "gdk_x11"
libNixName "geos_c" = return "geos"
libNixName "gdk-x11-3.0" = return "gtk3"
libNixName "gio-2.0" = return "glib"
libNixName "GL" = return "libGL"
libNixName "GLEW" = return "glew"
libNixName "GLU" = ["libGLU","libGL"]
libNixName "glut" = ["freeglut","libGLU","libGL"]
libNixName "gmodule" = return "glib"
libNixName "gmodule-2.0" = return "glib"
libNixName "gnome-keyring" = return "libgnome-keyring"
libNixName "gnome-keyring-1" = return "libgnome-keyring"
libNixName "gnome-vfs-2.0" = return "gnome-vfs"
libNixName "gnome-vfs-module-2.0" = return "gnome-vfs_module"
libNixName "gobject-2.0" = return "glib"
libNixName "gobject-introspection-1.0" = return "gobject-introspection"
libNixName "graphene-gobject-1.0" = return "graphene"
libNixName "gstreamer-audio-0.10" = return "gst-plugins-base"
libNixName "gstreamer-audio-1.0" = return "gst-plugins-base"
libNixName "gstreamer-base-0.10" = return "gst-plugins-base"
libNixName "gstreamer-base-1.0" = return "gst-plugins-base"
libNixName "gstreamer-controller-0.10" = return "gstreamer"
libNixName "gstreamer-dataprotocol-0.10" = return "gstreamer"
libNixName "gstreamer-net-0.10" = return "gst-plugins-base"
libNixName "gstreamer-plugins-base-0.10" = return "gst-plugins-base"
libNixName "gstreamer-video-1.0" = return "gst-plugins-base"
libNixName "gthread-2.0" = return "glib"
libNixName "gtk+-2.0" = return "gtk2"
libNixName "gtk+-3.0" = return "gtk3"
libNixName "gtk-x11-2.0" = return "gtk_x11"
libNixName "gtk4-atspi" = return "gtk4"
libNixName "gtk4-broadway" = return "gtk4"
libNixName "gtk4" = return "gtk4"
libNixName "gtk4-unix-print" = return "gtk4"
libNixName "gtk4-wayland" = return "gtk4"
libNixName "gtk4-x11" = return "gtk4"
libNixName "gtksourceview-3.0" = return "gtksourceview3"
libNixName "gtksourceview-5" = return "gtksourceview5"
libNixName "harfbuzz-gobject" = return "harfbuzz"
libNixName "harfbuzz-subset" = return "harfbuzz"
libNixName "hidapi-libusb" = return "hidapi"
libNixName "icu-i18n" = return "icu"
libNixName "icu-io" = return "icu"
libNixName "icu-uc" = return "icu"
libNixName "icudata" = return "icu"
libNixName "icui18n" = return "icu"
libNixName "icuio" = return "icu"
libNixName "icuuc" = return "icu"
libNixName "idn" = return "libidn"
libNixName "ImageMagick" = return "imagemagick"
libNixName "Imlib2" = return "imlib2"
libNixName "iw" = return "wirelesstools"
libNixName "jack" = return "libjack2"
libNixName "javascriptcoregtk" = return "webkitgtk"
libNixName "javascriptcoregtk-4.1" = return "webkitgtk_4_1"
libNixName "javascriptcoregtk-6.0" = return "webkitgtk_6_0"
libNixName "jpeg" = return "libjpeg"
libNixName "jvm" = return "jdk"
libNixName "lapack" = return "liblapack"
libNixName "lber" = return "openldap"
libNixName "ldap" = return "openldap"
libNixName "libavutil" = return "ffmpeg"
libNixName "libbrotlienc" = return "brotli"
libNixName "libbrotlidec" = return "brotli"
libNixName "libcurl" = return "curl"
libNixName "libcrypto" = return "openssl"
libNixName "libglog" = return "glog"
libNixName "libgsasl" = return "gsasl"
libNixName "liblzma" = return "xz"
libNixName "libnm" = return "networkmanager"
libNixName "libpcre" = return "pcre"
libNixName "libpcre2" = return "pcre2"
libNixName "libpcre2-8" = libNixName "libpcre2"
libNixName "libpipewire-0.3" = return "pipewire"
libNixName "libqrencode" = return "qrencode"
libNixName "libR" = return "R"
libNixName "libsecp256k1" = return "secp256k1"
libNixName "libsoup-2.4" = return "libsoup_2_4"
libNixName "libsoup-gnome-2.4" = return "libsoup_2_4"
libNixName "libsoup-3.0" = return "libsoup_3"
libNixName "libspa-0.2" = return "pipewire"
libNixName "libsystemd" = return "systemd"
libNixName "libudev" = return "systemd"
libNixName "libxml-2.0" = return "libxml2"
libNixName "libxxhash" = return "xxhash"
libNixName "libzip" = return "libzip"
libNixName "libzmq" = return "zeromq"
libNixName "liquid" = return "liquid-dsp"
libNixName "llama" = return "llama-cpp"
libNixName "lzma" = return "xz"
libNixName "m" = [] -- in stdenv
libNixName "magic" = return "file"
libNixName "MagickWand" = return "imagemagick"
libNixName "mnl" = return "libmnl"
libNixName "mpi" = return "openmpi"
libNixName "mysql" = return "mariadb"
libNixName "ncursesw" = return "ncurses"
libNixName "netsnmp" = return "net-snmp"
libNixName "nix-cmd" = return "nix"
libNixName "nix-expr-c" = return "nix"
libNixName "nix-expr" = return "nix"
libNixName "nix-fetchers-c" = return "nix"
libNixName "nix-fetchers" = return "nix"
libNixName "nix-flake-c" = return "nix"
libNixName "nix-flake" = return "nix"
libNixName "nix-main-c" = return "nix"
libNixName "nix-main" = return "nix"
libNixName "nix-store-c" = return "nix"
libNixName "nix-store" = return "nix"
libNixName "nix-util-c" = return "nix"
libNixName "nix-util" = return "nix"
libNixName "notify" = return "libnotify"
libNixName "odbc" = return "unixODBC"
libNixName "openblas" = return "openblasCompat"
libNixName "panelw" = return "ncurses"
libNixName "pangocairo" = return "pango"
libNixName "pcap" = return "libpcap"
libNixName "pfs-1.2" = return "pfstools"
libNixName "png" = return "libpng"
libNixName "poppler-cpp" = return "poppler"
libNixName "poppler-glib" = return "poppler_gi"
libNixName "pq" = return "libpq"
libNixName "pthread" = []
libNixName "pulse" = return "libpulseaudio"
libNixName "pulse-simple" = return "libpulseaudio"
libNixName "python-3.3" = return "python33"
libNixName "python-3.4" = return "python34"
libNixName "python3-embed" = return "python3"
libNixName "Qt5Core" = return "qt5"
libNixName "Qt5Gui" = return "qt5"
libNixName "Qt5Qml" = return "qt5"
libNixName "Qt5Quick" = return "qt5"
libNixName "Qt5Widgets" = return "qt5"
libNixName "quadprog" = return "QuadProgpp"
libNixName "rt" = [] -- in glibc
libNixName "rtlsdr" = return "rtl-sdr"
libNixName "ruby1.8" = return "ruby"
libNixName "sass" = return "libsass"
libNixName "sctp" = return "lksctp-tools" -- This is linux-specific, we should create a common attribute if we ever add sctp support for other systems.
libNixName "sdl2" = return "SDL2"
libNixName "sndfile" = return "libsndfile"
libNixName "SoapySDR" = return "soapysdr"
libNixName "sodium" = return "libsodium"
libNixName "sqlite3" = return "sqlite"
libNixName "ssh2" = return "libssh2"
libNixName "ssl" = return "openssl"
libNixName "statgrab" = return "libstatgrab"
libNixName "stdc++" = [] -- What is that?
libNixName "stdc++.dll" = [] -- What is that?
libNixName "systemd-journal" = return "systemd"
libNixName "tag_c" = return "taglib"
libNixName "taglib_c" = return "taglib"
libNixName "tdjson" = return "tdlib"
libNixName "tensorflow" = return "libtensorflow"
libNixName "udev" = return "systemd";
libNixName "uuid" = return "libossp_uuid";
libNixName "vte-2.91" = return "vte"
libNixName "vulkan" = return "vulkan-loader"
libNixName "wayland-client" = return "wayland"
libNixName "wayland-cursor" = return "wayland"
libNixName "wayland-egl" = return "libGL"
libNixName "wayland-server" = return "wayland"
libNixName "webkit" = return "webkitgtk" -- this is an alias, so it only works for downstream expressions not in hackage-packages.nix
libNixName "webkit2gtk" = return "webkitgtk"
libNixName "webkit2gtk-4.1" = return "webkitgtk_4_1"
libNixName "webkit2gtk-6.0" = return "webkitgtk_6_0"
libNixName "webkit2gtk-web-extension-4.1" = return "webkitgtk_4_1"
libNixName "webkit2gtk-web-extension-6.0" = return "webkitgtk_6_0"
libNixName "wxGTK" = return "wxGTK32"
libNixName "X11" = return "libx11"
libNixName "x11" = return "libx11"
libNixName "xau" = return "libxau"
libNixName "Xcursor" = return "libxcursor"
libNixName "xerces-c" = return "xercesc"
libNixName "Xext" = return "libxext"
libNixName "xft" = return "libxft"
libNixName "Xi" = return "libxi"
libNixName "Xinerama" = return "libxinerama"
libNixName "xkbcommon" = return "libxkbcommon"
libNixName "xml2" = return "libxml2"
libNixName "Xpm" = return "libxpm"
libNixName "Xrandr" = return "libxrandr"
libNixName "Xrender" = return "libxrender"
libNixName "xscrnsaver" = return "libxscrnsaver"
libNixName "Xss" = return "libxscrnsaver"
libNixName "Xtst" = return "libxtst"
libNixName "Xxf86vm" = return "libxxf86vm"
libNixName "yaml" = return "libyaml"
libNixName "yaml-0.1" = return "libyaml"
libNixName "z" = return "zlib"
libNixName "zmq" = return "zeromq"
libNixName "TKBO" = return "opencascade-occt"
libNixName "TKBRep" = return "opencascade-occt"
libNixName "TKBin" = return "opencascade-occt"
libNixName "TKBinL" = return "opencascade-occt"
libNixName "TKBinTObj" = return "opencascade-occt"
libNixName "TKBinXCAF" = return "opencascade-occt"
libNixName "TKBool" = return "opencascade-occt"
libNixName "TKCAF" = return "opencascade-occt"
libNixName "TKCDF" = return "opencascade-occt"
libNixName "TKDCAF" = return "opencascade-occt"
libNixName "TKDE" = return "opencascade-occt"
libNixName "TKDECascade" = return "opencascade-occt"
libNixName "TKDEGLTF" = return "opencascade-occt"
libNixName "TKDEIGES" = return "opencascade-occt"
libNixName "TKDEOBJ" = return "opencascade-occt"
libNixName "TKDEPLY" = return "opencascade-occt"
libNixName "TKDESTEP" = return "opencascade-occt"
libNixName "TKDESTL" = return "opencascade-occt"
libNixName "TKDEVRML" = return "opencascade-occt"
libNixName "TKDraw" = return "opencascade-occt"
libNixName "TKExpress" = return "opencascade-occt"
libNixName "TKFeat" = return "opencascade-occt"
libNixName "TKFillet" = return "opencascade-occt"
libNixName "TKG2d" = return "opencascade-occt"
libNixName "TKG3d" = return "opencascade-occt"
libNixName "TKGeomAlgo" = return "opencascade-occt"
libNixName "TKGeomBase" = return "opencascade-occt"
libNixName "TKHLR" = return "opencascade-occt"
libNixName "TKLCAF" = return "opencascade-occt"
libNixName "TKMath" = return "opencascade-occt"
libNixName "TKMesh" = return "opencascade-occt"
libNixName "TKMeshVS" = return "opencascade-occt"
libNixName "TKOffset" = return "opencascade-occt"
libNixName "TKOpenGl" = return "opencascade-occt"
libNixName "TKOpenGlTest" = return "opencascade-occt"
libNixName "TKPrim" = return "opencascade-occt"
libNixName "TKQADraw" = return "opencascade-occt"
libNixName "TKRWMesh" = return "opencascade-occt"
libNixName "TKService" = return "opencascade-occt"
libNixName "TKShHealing" = return "opencascade-occt"
libNixName "TKStd" = return "opencascade-occt"
libNixName "TKStdL" = return "opencascade-occt"
libNixName "TKTObj" = return "opencascade-occt"
libNixName "TKTObjDRAW" = return "opencascade-occt"
libNixName "TKTopAlgo" = return "opencascade-occt"
libNixName "TKTopTest" = return "opencascade-occt"
libNixName "TKV3d" = return "opencascade-occt"
libNixName "TKVCAF" = return "opencascade-occt"
libNixName "TKViewerTest" = return "opencascade-occt"
libNixName "TKXCAF" = return "opencascade-occt"
libNixName "TKXDEDRAW" = return "opencascade-occt"
libNixName "TKXMesh" = return "opencascade-occt"
libNixName "TKXSBase" = return "opencascade-occt"
libNixName "TKXSDRAW" = return "opencascade-occt"
libNixName "TKXSDRAWDE" = return "opencascade-occt"
libNixName "TKXSDRAWGLTF" = return "opencascade-occt"
libNixName "TKXSDRAWIGES" = return "opencascade-occt"
libNixName "TKXSDRAWOBJ" = return "opencascade-occt"
libNixName "TKXSDRAWPLY" = return "opencascade-occt"
libNixName "TKXSDRAWSTEP" = return "opencascade-occt"
libNixName "TKXSDRAWSTL" = return "opencascade-occt"
libNixName "TKXSDRAWVRML" = return "opencascade-occt"
libNixName "TKXml" = return "opencascade-occt"
libNixName "TKXmlL" = return "opencascade-occt"
libNixName "TKXmlTObj" = return "opencascade-occt"
libNixName "TKXmlXCAF" = return "opencascade-occt"
libNixName "TKernel" = return "opencascade-occt"
libNixName x = return (guessNixIdentifier x)
-- | Map build tool names to Nix attribute names.
buildToolNixName :: String -> [Identifier]
buildToolNixName "" = return (error "buildToolNixName: invalid empty dependency name")
buildToolNixName "cabal" = return "cabal-install"
buildToolNixName "fltk-config" = return "fltk"
buildToolNixName "ghc" = []
buildToolNixName "gtk2hsC2hs" = return "gtk2hs-buildtools"
buildToolNixName "gtk2hsHookGenerator" = return "gtk2hs-buildtools"
buildToolNixName "gtk2hsTypeGen" = return "gtk2hs-buildtools"
buildToolNixName "hsc2hs" = []
buildToolNixName "utillinux" = return "util-linux"
buildToolNixName x = return (fromString x)
-- | Helper function to extract the package name from a String that may or may
-- not be formatted like a Cabal package identifier.
--
-- >>> guessNixIdentifier "foo-1.0"
-- Identifier "foo"
-- >>> guessNixIdentifier "foo"
-- Identifier "foo"
-- >>> guessNixIdentifier "foo - 0"
-- Identifier "foo - 0"
-- >>> guessNixIdentifier "1foo-1.0"
-- Identifier "1foo"
-- >>> guessNixIdentifier "-foo-1.0"
-- Identifier "-foo-1.0"
guessNixIdentifier :: String -> Identifier
guessNixIdentifier x = fromString (fromMaybe x maybePackageId)
where
maybePackageId = unPackageName . pkgName <$> simpleParse x