distros.nim 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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 strutils import contains, toLowerAscii
  29. when not defined(nimscript):
  30. from osproc import execProcess
  31. from os 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. 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. BSD
  122. FreeBSD
  123. OpenBSD
  124. DragonFlyBSD
  125. Haiku
  126. const
  127. LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware,
  128. Distribution.ArchLinux}
  129. # we cache the result of the 'cmdRelease'
  130. # execution for faster platform detections.
  131. var unameRes, osReleaseIDRes, releaseRes, hostnamectlRes: string
  132. template cmdRelease(cmd, cache): untyped =
  133. if cache.len == 0:
  134. cache = (when defined(nimscript): gorge(cmd) else: execProcess(cmd))
  135. cache
  136. template uname(): untyped = cmdRelease("uname -a", unameRes)
  137. template osReleaseID(): untyped = cmdRelease("cat /etc/os-release | grep ^ID=", osReleaseIDRes)
  138. template release(): untyped = cmdRelease("lsb_release -d", releaseRes)
  139. template hostnamectl(): untyped = cmdRelease("hostnamectl", hostnamectlRes)
  140. proc detectOsWithAllCmd(d: Distribution): bool =
  141. let dd = toLowerAscii($d)
  142. result = dd in toLowerAscii(osReleaseID()) or dd in toLowerAscii(release()) or
  143. dd in toLowerAscii(uname()) or ("operating system: " & dd) in toLowerAscii(hostnamectl())
  144. proc detectOsImpl(d: Distribution): bool =
  145. case d
  146. of Distribution.Windows: ## some version of Windows
  147. result = defined(windows)
  148. of Distribution.Posix: result = defined(posix)
  149. of Distribution.MacOSX: result = defined(macosx)
  150. of Distribution.Linux: result = defined(linux)
  151. of Distribution.BSD: result = defined(bsd)
  152. else:
  153. when defined(bsd):
  154. case d
  155. of Distribution.FreeBSD, Distribution.OpenBSD:
  156. result = $d in uname()
  157. else:
  158. result = false
  159. elif defined(linux):
  160. case d
  161. of Distribution.Gentoo:
  162. result = ("-" & $d & " ") in uname()
  163. of Distribution.Elementary, Distribution.Ubuntu, Distribution.Debian, Distribution.Fedora,
  164. Distribution.OpenMandriva, Distribution.CentOS, Distribution.Alpine,
  165. Distribution.Mageia, Distribution.Zorin:
  166. result = toLowerAscii($d) in osReleaseID()
  167. of Distribution.RedHat:
  168. result = "rhel" in osReleaseID()
  169. of Distribution.ArchLinux:
  170. result = "arch" in osReleaseID()
  171. of Distribution.NixOS:
  172. result = existsEnv("NIX_BUILD_TOP") or existsEnv("__NIXOS_SET_ENVIRONMENT_DONE")
  173. # Check if this is a Nix build or NixOS environment
  174. of Distribution.OpenSUSE:
  175. result = "suse" in toLowerAscii(uname()) or "suse" in toLowerAscii(release())
  176. of Distribution.GoboLinux:
  177. result = "-Gobo " in uname()
  178. of Distribution.Solaris:
  179. let uname = toLowerAscii(uname())
  180. result = ("sun" in uname) or ("solaris" in uname)
  181. of Distribution.Haiku:
  182. result = defined(haiku)
  183. else:
  184. result = detectOsWithAllCmd(d)
  185. else:
  186. result = false
  187. template detectOs*(d: untyped): bool =
  188. ## Distro/OS detection. For convenience the
  189. ## required ``Distribution.`` qualifier is added to the
  190. ## enum value.
  191. detectOsImpl(Distribution.d)
  192. when not defined(nimble):
  193. var foreignDeps: seq[string] = @[]
  194. proc foreignCmd*(cmd: string; requiresSudo = false) =
  195. ## Registers a foreign command to the intern list of commands
  196. ## that can be queried later.
  197. let c = (if requiresSudo: "sudo " else: "") & cmd
  198. when defined(nimble):
  199. nimscriptapi.foreignDeps.add(c)
  200. else:
  201. foreignDeps.add(c)
  202. proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) =
  203. ## Returns the distro's native command line to install 'foreignPackageName'
  204. ## and whether it requires root/admin rights.
  205. let p = foreignPackageName
  206. when defined(windows):
  207. result = ("Chocolatey install " & p, false)
  208. elif defined(bsd):
  209. result = ("ports install " & p, true)
  210. elif defined(linux):
  211. if detectOs(Ubuntu) or detectOs(Elementary) or detectOs(Debian) or
  212. detectOs(KNOPPIX) or detectOs(SteamOS):
  213. result = ("apt-get install " & p, true)
  214. elif detectOs(Gentoo):
  215. result = ("emerge install " & p, true)
  216. elif detectOs(Fedora):
  217. result = ("yum install " & p, true)
  218. elif detectOs(RedHat):
  219. result = ("rpm install " & p, true)
  220. elif detectOs(OpenSUSE):
  221. result = ("yast -i " & p, true)
  222. elif detectOs(Slackware):
  223. result = ("installpkg " & p, true)
  224. elif detectOs(OpenMandriva):
  225. result = ("urpmi " & p, true)
  226. elif detectOs(ZenWalk):
  227. result = ("netpkg install " & p, true)
  228. elif detectOs(NixOS):
  229. result = ("nix-env -i " & p, false)
  230. elif detectOs(Solaris) or detectOs(FreeBSD):
  231. result = ("pkg install " & p, true)
  232. elif detectOs(OpenBSD):
  233. result = ("pkg_add " & p, true)
  234. elif detectOs(PCLinuxOS):
  235. result = ("rpm -ivh " & p, true)
  236. elif detectOs(ArchLinux) or detectOs(Manjaro):
  237. result = ("pacman -S " & p, true)
  238. else:
  239. result = ("<your package manager here> install " & p, true)
  240. elif defined(haiku):
  241. result = ("pkgman install " & p, true)
  242. else:
  243. result = ("brew install " & p, false)
  244. proc foreignDep*(foreignPackageName: string) =
  245. ## Registers 'foreignPackageName' to the internal list of foreign deps.
  246. ## It is your job to ensure the package name
  247. let (installCmd, sudo) = foreignDepInstallCmd(foreignPackageName)
  248. foreignCmd installCmd, sudo
  249. proc echoForeignDeps*() =
  250. ## Writes the list of registered foreign deps to stdout.
  251. for d in foreignDeps:
  252. echo d
  253. when false:
  254. foreignDep("libblas-dev")
  255. foreignDep "libfoo"
  256. echoForeignDeps()