distros.nim 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2016 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module implements the basics for Linux distribution ("distro")
  10. ## detection and the OS's native package manager. Its primary purpose is to
  11. ## produce output for Nimble packages, like:
  12. ##
  13. ## To complete the installation, run:
  14. ##
  15. ## sudo apt-get install libblas-dev
  16. ## sudo apt-get install libvoodoo
  17. ##
  18. ## The above output could be the result of a code snippet like:
  19. ##
  20. ## .. code-block:: nim
  21. ##
  22. ## if detectOs(Ubuntu):
  23. ## foreignDep "lbiblas-dev"
  24. ## foreignDep "libvoodoo"
  25. ##
  26. ##
  27. ## See `packaging <packaging.html>`_ for hints on distributing Nim using OS packages.
  28. from std/strutils import contains, toLowerAscii
  29. when not defined(nimscript):
  30. from std/osproc import execProcess
  31. from std/envvars import existsEnv
  32. type
  33. Distribution* {.pure.} = enum ## the list of known distributions
  34. Windows ## some version of Windows
  35. Posix ## some POSIX system
  36. MacOSX ## some version of OSX
  37. Linux ## some version of Linux
  38. Ubuntu
  39. Debian
  40. Gentoo
  41. Fedora
  42. RedHat
  43. OpenSUSE
  44. Manjaro
  45. Elementary
  46. Zorin
  47. CentOS
  48. Deepin
  49. ArchLinux
  50. Artix
  51. Antergos
  52. PCLinuxOS
  53. Mageia
  54. LXLE
  55. Solus
  56. Lite
  57. Slackware
  58. Androidx86
  59. Puppy
  60. Peppermint
  61. Tails
  62. AntiX
  63. Kali
  64. SparkyLinux
  65. Apricity
  66. BlackLab
  67. Bodhi
  68. TrueOS
  69. ArchBang
  70. KaOS
  71. WattOS
  72. Korora
  73. Simplicity
  74. RemixOS
  75. OpenMandriva
  76. Netrunner
  77. Alpine
  78. BlackArch
  79. Ultimate
  80. Gecko
  81. Parrot
  82. KNOPPIX
  83. GhostBSD
  84. Sabayon
  85. Salix
  86. Q4OS
  87. ClearOS
  88. Container
  89. ROSA
  90. Zenwalk
  91. Parabola
  92. ChaletOS
  93. BackBox
  94. MXLinux
  95. Vector
  96. Maui
  97. Qubes
  98. RancherOS
  99. Oracle
  100. TinyCore
  101. Robolinux
  102. Trisquel
  103. Voyager
  104. Clonezilla
  105. SteamOS
  106. Absolute
  107. NixOS ## NixOS or a Nix build environment
  108. AUSTRUMI
  109. Arya
  110. Porteus
  111. AVLinux
  112. Elive
  113. Bluestar
  114. SliTaz
  115. Solaris
  116. Chakra
  117. Wifislax
  118. Scientific
  119. ExTiX
  120. Rockstor
  121. GoboLinux
  122. Void
  123. BSD
  124. FreeBSD
  125. OpenBSD
  126. DragonFlyBSD
  127. Haiku
  128. const
  129. LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware,
  130. Distribution.ArchLinux, Distribution.Artix, Distribution.Antergos,
  131. Distribution.BlackArch, Distribution.ArchBang}
  132. # we cache the result of the 'cmdRelease'
  133. # execution for faster platform detections.
  134. var unameRes, osReleaseIDRes, releaseRes, hostnamectlRes: string
  135. template cmdRelease(cmd, cache): untyped =
  136. if cache.len == 0:
  137. cache = (when defined(nimscript): gorge(cmd) else: execProcess(cmd))
  138. cache
  139. template uname(): untyped = cmdRelease("uname -a", unameRes)
  140. template osReleaseID(): untyped = cmdRelease("cat /etc/os-release | grep ^ID=", osReleaseIDRes)
  141. template release(): untyped = cmdRelease("lsb_release -d", releaseRes)
  142. template hostnamectl(): untyped = cmdRelease("hostnamectl", hostnamectlRes)
  143. proc detectOsWithAllCmd(d: Distribution): bool =
  144. let dd = toLowerAscii($d)
  145. result = dd in toLowerAscii(osReleaseID()) or dd in toLowerAscii(release()) or
  146. dd in toLowerAscii(uname()) or ("operating system: " & dd) in
  147. toLowerAscii(hostnamectl())
  148. proc detectOsImpl(d: Distribution): bool =
  149. case d
  150. of Distribution.Windows: result = defined(windows)
  151. of Distribution.Posix: result = defined(posix)
  152. of Distribution.MacOSX: result = defined(macosx)
  153. of Distribution.Linux: result = defined(linux)
  154. of Distribution.BSD: result = defined(bsd)
  155. else:
  156. when defined(bsd):
  157. case d
  158. of Distribution.FreeBSD, Distribution.OpenBSD:
  159. result = $d in uname()
  160. else:
  161. result = false
  162. elif defined(linux):
  163. case d
  164. of Distribution.Gentoo:
  165. result = ("-" & $d & " ") in uname()
  166. of Distribution.Elementary, Distribution.Ubuntu, Distribution.Debian,
  167. Distribution.Fedora, Distribution.OpenMandriva, Distribution.CentOS,
  168. Distribution.Alpine, Distribution.Mageia, Distribution.Zorin, Distribution.Void:
  169. result = toLowerAscii($d) in osReleaseID()
  170. of Distribution.RedHat:
  171. result = "rhel" in osReleaseID()
  172. of Distribution.ArchLinux:
  173. result = "arch" in osReleaseID()
  174. of Distribution.Artix:
  175. result = "artix" in osReleaseID()
  176. of Distribution.NixOS:
  177. # Check if this is a Nix build or NixOS environment
  178. result = existsEnv("NIX_BUILD_TOP") or existsEnv("__NIXOS_SET_ENVIRONMENT_DONE")
  179. of Distribution.OpenSUSE:
  180. result = "suse" in toLowerAscii(uname()) or "suse" in toLowerAscii(release())
  181. of Distribution.GoboLinux:
  182. result = "-Gobo " in uname()
  183. of Distribution.Solaris:
  184. let uname = toLowerAscii(uname())
  185. result = ("sun" in uname) or ("solaris" in uname)
  186. of Distribution.Haiku:
  187. result = defined(haiku)
  188. else:
  189. result = detectOsWithAllCmd(d)
  190. else:
  191. result = false
  192. template detectOs*(d: untyped): bool =
  193. ## Distro/OS detection. For convenience, the
  194. ## required `Distribution.` qualifier is added to the
  195. ## enum value.
  196. detectOsImpl(Distribution.d)
  197. when not defined(nimble):
  198. var foreignDeps*: seq[string] = @[] ## Registered foreign deps.
  199. proc foreignCmd*(cmd: string; requiresSudo = false) =
  200. ## Registers a foreign command to the internal list of commands
  201. ## that can be queried later.
  202. let c = (if requiresSudo: "sudo " else: "") & cmd
  203. when defined(nimble):
  204. nimscriptapi.foreignDeps.add(c)
  205. else:
  206. foreignDeps.add(c)
  207. proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) =
  208. ## Returns the distro's native command to install `foreignPackageName`
  209. ## and whether it requires root/admin rights.
  210. let p = foreignPackageName
  211. when defined(windows):
  212. result = ("choco install " & p, false)
  213. elif defined(bsd):
  214. result = ("ports install " & p, true)
  215. elif defined(linux):
  216. if detectOs(Ubuntu) or detectOs(Elementary) or detectOs(Debian) or
  217. detectOs(KNOPPIX) or detectOs(SteamOS):
  218. result = ("apt-get install " & p, true)
  219. elif detectOs(Gentoo):
  220. result = ("emerge install " & p, true)
  221. elif detectOs(Fedora):
  222. result = ("yum install " & p, true)
  223. elif detectOs(RedHat):
  224. result = ("rpm install " & p, true)
  225. elif detectOs(OpenSUSE):
  226. result = ("yast -i " & p, true)
  227. elif detectOs(Slackware):
  228. result = ("installpkg " & p, true)
  229. elif detectOs(OpenMandriva):
  230. result = ("urpmi " & p, true)
  231. elif detectOs(ZenWalk):
  232. result = ("netpkg install " & p, true)
  233. elif detectOs(NixOS):
  234. result = ("nix-env -i " & p, false)
  235. elif detectOs(Solaris) or detectOs(FreeBSD):
  236. result = ("pkg install " & p, true)
  237. elif detectOs(OpenBSD):
  238. result = ("pkg_add " & p, true)
  239. elif detectOs(PCLinuxOS):
  240. result = ("rpm -ivh " & p, true)
  241. elif detectOs(ArchLinux) or detectOs(Manjaro) or detectOs(Artix):
  242. result = ("pacman -S " & p, true)
  243. elif detectOs(Void):
  244. result = ("xbps-install " & p, true)
  245. else:
  246. result = ("<your package manager here> install " & p, true)
  247. elif defined(haiku):
  248. result = ("pkgman install " & p, true)
  249. else:
  250. result = ("brew install " & p, false)
  251. proc foreignDep*(foreignPackageName: string) =
  252. ## Registers `foreignPackageName` to the internal list of foreign deps.
  253. ## It is your job to ensure that the package name is correct.
  254. let (installCmd, sudo) = foreignDepInstallCmd(foreignPackageName)
  255. foreignCmd(installCmd, sudo)
  256. proc echoForeignDeps*() =
  257. ## Writes the list of registered foreign deps to stdout.
  258. for d in foreignDeps:
  259. echo d