distros.nim 7.7 KB

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