distros.nim 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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 libblas-dev
  16. ## sudo apt-get 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. from strutils import contains, toLowerAscii
  27. when not defined(nimscript):
  28. from osproc import execProcess
  29. from os import existsEnv
  30. type
  31. Distribution* {.pure.} = enum ## the list of known distributions
  32. Windows ## some version of Windows
  33. Posix ## some Posix system
  34. MacOSX ## some version of OSX
  35. Linux ## some version of Linux
  36. Ubuntu
  37. Debian
  38. Gentoo
  39. Fedora
  40. RedHat
  41. OpenSUSE
  42. Manjaro
  43. Elementary
  44. Zorin
  45. CentOS
  46. Deepin
  47. ArchLinux
  48. Antergos
  49. PCLinuxOS
  50. Mageia
  51. LXLE
  52. Solus
  53. Lite
  54. Slackware
  55. Androidx86
  56. Puppy
  57. Peppermint
  58. Tails
  59. AntiX
  60. Kali
  61. SparkyLinux
  62. Apricity
  63. BlackLab
  64. Bodhi
  65. TrueOS
  66. ArchBang
  67. KaOS
  68. WattOS
  69. Korora
  70. Simplicity
  71. RemixOS
  72. OpenMandriva
  73. Netrunner
  74. Alpine
  75. BlackArch
  76. Ultimate
  77. Gecko
  78. Parrot
  79. KNOPPIX
  80. GhostBSD
  81. Sabayon
  82. Salix
  83. Q4OS
  84. ClearOS
  85. Container
  86. ROSA
  87. Zenwalk
  88. Parabola
  89. ChaletOS
  90. BackBox
  91. MXLinux
  92. Vector
  93. Maui
  94. Qubes
  95. RancherOS
  96. Oracle
  97. TinyCore
  98. Robolinux
  99. Trisquel
  100. Voyager
  101. Clonezilla
  102. SteamOS
  103. Absolute
  104. NixOS ## NixOS or a Nix build environment
  105. AUSTRUMI
  106. Arya
  107. Porteus
  108. AVLinux
  109. Elive
  110. Bluestar
  111. SliTaz
  112. Solaris
  113. Chakra
  114. Wifislax
  115. Scientific
  116. ExTiX
  117. Rockstor
  118. GoboLinux
  119. BSD
  120. FreeBSD
  121. OpenBSD
  122. DragonFlyBSD
  123. Haiku
  124. const
  125. LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware,
  126. Distribution.ArchLinux}
  127. # we cache the result of the 'uname -a'
  128. # execution for faster platform detections.
  129. var unameRes, releaseRes, hostnamectlRes: string
  130. template unameRelease(cmd, cache): untyped =
  131. if cache.len == 0:
  132. cache = (when defined(nimscript): gorge(cmd) else: execProcess(cmd))
  133. cache
  134. template uname(): untyped = unameRelease("uname -a", unameRes)
  135. template release(): untyped = unameRelease("lsb_release -d", releaseRes)
  136. template hostnamectl(): untyped = unameRelease("hostnamectl", hostnamectlRes)
  137. proc detectOsImpl(d: Distribution): bool =
  138. case d
  139. of Distribution.Windows: ## some version of Windows
  140. result = defined(windows)
  141. of Distribution.Posix: result = defined(posix)
  142. of Distribution.MacOSX: result = defined(macosx)
  143. of Distribution.Linux: result = defined(linux)
  144. of Distribution.Ubuntu, Distribution.Gentoo, Distribution.FreeBSD,
  145. Distribution.OpenBSD:
  146. result = ("-" & $d & " ") in uname()
  147. of Distribution.RedHat:
  148. result = "Red Hat" in uname()
  149. of Distribution.BSD: result = defined(bsd)
  150. of Distribution.ArchLinux:
  151. result = "arch" in toLowerAscii(uname())
  152. of Distribution.NixOS:
  153. result = existsEnv("NIX_BUILD_TOP") or existsEnv("__NIXOS_SET_ENVIRONMENT_DONE")
  154. # Check if this is a Nix build or NixOS environment
  155. of Distribution.OpenSUSE:
  156. result = "suse" in toLowerAscii(uname()) or "suse" in toLowerAscii(release())
  157. of Distribution.GoboLinux:
  158. result = "-Gobo " in uname()
  159. of Distribution.OpenMandriva:
  160. result = "mandriva" in toLowerAscii(uname())
  161. of Distribution.Solaris:
  162. let uname = toLowerAscii(uname())
  163. result = ("sun" in uname) or ("solaris" in uname)
  164. of Distribution.Haiku:
  165. result = defined(haiku)
  166. else:
  167. let dd = toLowerAscii($d)
  168. result = dd in toLowerAscii(uname()) or dd in toLowerAscii(release()) or
  169. ("operating system: " & dd) in toLowerAscii(hostnamectl())
  170. template detectOs*(d: untyped): bool =
  171. ## Distro/OS detection. For convenience the
  172. ## required ``Distribution.`` qualifier is added to the
  173. ## enum value.
  174. detectOsImpl(Distribution.d)
  175. when not defined(nimble):
  176. var foreignDeps: seq[string] = @[]
  177. proc foreignCmd*(cmd: string; requiresSudo = false) =
  178. ## Registers a foreign command to the intern list of commands
  179. ## that can be queried later.
  180. let c = (if requiresSudo: "sudo " else: "") & cmd
  181. when defined(nimble):
  182. nimscriptapi.foreignDeps.add(c)
  183. else:
  184. foreignDeps.add(c)
  185. proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) =
  186. ## Returns the distro's native command line to install 'foreignPackageName'
  187. ## and whether it requires root/admin rights.
  188. let p = foreignPackageName
  189. when defined(windows):
  190. result = ("Chocolatey install " & p, false)
  191. elif defined(bsd):
  192. result = ("ports install " & p, true)
  193. elif defined(linux):
  194. if detectOs(Ubuntu) or detectOs(Elementary) or detectOs(Debian) or
  195. detectOs(KNOPPIX) or detectOs(SteamOS):
  196. result = ("apt-get install " & p, true)
  197. elif detectOs(Gentoo):
  198. result = ("emerge install " & p, true)
  199. elif detectOs(Fedora):
  200. result = ("yum install " & p, true)
  201. elif detectOs(RedHat):
  202. result = ("rpm install " & p, true)
  203. elif detectOs(OpenSUSE):
  204. result = ("yast -i " & p, true)
  205. elif detectOs(Slackware):
  206. result = ("installpkg " & p, true)
  207. elif detectOs(OpenMandriva):
  208. result = ("urpmi " & p, true)
  209. elif detectOs(ZenWalk):
  210. result = ("netpkg install " & p, true)
  211. elif detectOs(NixOS):
  212. result = ("nix-env -i " & p, false)
  213. elif detectOs(Solaris):
  214. result = ("pkg install " & p, true)
  215. elif detectOs(PCLinuxOS):
  216. result = ("rpm -ivh " & p, true)
  217. elif detectOs(ArchLinux) or detectOs(Manjaro):
  218. result = ("pacman -S " & p, true)
  219. else:
  220. result = ("<your package manager here> install " & p, true)
  221. elif defined(haiku):
  222. result = ("pkgman install " & p, true)
  223. else:
  224. result = ("brew install " & p, false)
  225. proc foreignDep*(foreignPackageName: string) =
  226. ## Registers 'foreignPackageName' to the internal list of foreign deps.
  227. ## It is your job to ensure the package name
  228. let (installCmd, sudo) = foreignDepInstallCmd(foreignPackageName)
  229. foreignCmd installCmd, sudo
  230. proc echoForeignDeps*() =
  231. ## Writes the list of registered foreign deps to stdout.
  232. for d in foreignDeps:
  233. echo d
  234. when false:
  235. foreignDep("libblas-dev")
  236. foreignDep "libfoo"
  237. echoForeignDeps()