Automate installation of DXVK, D9VK + Wine/Wine Staging & update GPU drivers + PlayonLinux wineprefixes (Debian/Ubuntu/Mint/Arch Linux/Manjaro)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

603 lines
15 KiB

  1. #!/bin/env bash
  2. # Compile latest Nvidia drivers on a Debian-based Linux
  3. # Copyright (C) 2019 Pekka Helenius
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. ##############################################################################
  18. # Check if we're using bash or sh to run the script. If bash, OK.
  19. # If another one, ask user to run the script with bash.
  20. BASH_CHECK=$(ps | grep `echo $$` | awk '{ print $4 }')
  21. if [ $BASH_CHECK != "bash" ]; then
  22. echo "
  23. Please run this script using bash (/usr/bin/bash).
  24. "
  25. exit 1
  26. fi
  27. ########################################################
  28. # Just a title & author for this script, used in initialization
  29. SCRIPT_TITLE="\e[1mNvidia drivers package builder & installer\e[0m"
  30. SCRIPT_AUTHOR="Pekka Helenius (~Fincer), 2019"
  31. ########################################################
  32. BUILD_MAINDIR=${PWD}/debian_nvidia
  33. ########################################################
  34. _pkgname="nvidia"
  35. arch="x86_64"
  36. pkgver=430.14
  37. files=(
  38. "http://archive.ubuntu.com/ubuntu/pool/restricted/n/nvidia-graphics-drivers-418/nvidia-graphics-drivers-418_418.56-0ubuntu1.debian.tar.xz"
  39. "http://us.download.nvidia.com/XFree86/Linux-${arch}/${pkgver}/NVIDIA-Linux-${arch}-${pkgver}.run"
  40. )
  41. ###################
  42. pkgver_major=$(printf '%s' ${pkgver} | grep -oE "^[0-9]+[^.]")
  43. pkgdir="nvidia-graphics-drivers-${pkgver_major}_${pkgver}"
  44. typeset -A library_fixes
  45. ###################
  46. # From time to time, bundled library version numbers change
  47. # in Nvidia driver packages. Update library version if needed
  48. #
  49. # Left side: old library version
  50. # Right side: new library version
  51. #
  52. library_fixes=(
  53. [libnvidia-egl-wayland.so.1.0.2]='libnvidia-egl-wayland.so.1.0.3'
  54. )
  55. ###################
  56. # These are defined build dependencies in debian/control file
  57. nvidia_builddeps=(
  58. 'dpkg-dev'
  59. 'xz-utils'
  60. 'dkms'
  61. 'libwayland-client0'
  62. 'libwayland-server0'
  63. 'libxext6'
  64. 'quilt'
  65. 'po-debconf'
  66. 'execstack'
  67. 'dh-modaliases'
  68. 'xserver-xorg-dev'
  69. 'libglvnd-dev'
  70. )
  71. ###################
  72. # These packages are required by the compiled Nvidia packages
  73. nvidia_required_packages=(
  74. # Required by libnvidia-gl
  75. 'libwayland-client0'
  76. 'libwayland-server0'
  77. # Required by libnvidia, libnvidia-decode & libnvidia-fbc1
  78. 'libx11-6'
  79. # Required by libnvidia, libnvidia-decode, libnvidia-fbc1 & libnvidia-ifr1
  80. 'libxext6'
  81. # Required by libnvidia-fbc1 & libnvidia-ifr1
  82. 'libgl1'
  83. # Required by xserver-xorg-video-nvidia
  84. 'xserver-xorg-core'
  85. 'xorg-video-abi-23'
  86. # Required by nvidia-compute-utils
  87. 'adduser'
  88. )
  89. ###################
  90. # Nvidia packages. THIS ORDER IS MANDATORY, DO NOT CHANGE!
  91. nvidia_install_packages=(
  92. # Similar than 'nvidia-dkms' package on Arch Linux
  93. "nvidia-kernel-source-${pkgver_major}"
  94. # Nvidia DKMS
  95. "nvidia-kernel-common-${pkgver_major}"
  96. "nvidia-dkms-${pkgver_major}"
  97. # Similar than 'nvidia-utils' package on Arch Linux
  98. "libnvidia-common-${pkgver_major}"
  99. "libnvidia-gl-${pkgver_major}"
  100. "libnvidia-cfg1-${pkgver_major}"
  101. "xserver-xorg-video-nvidia-${pkgver_major}"
  102. "libnvidia-compute-${pkgver_major}"
  103. "libnvidia-decode-${pkgver_major}"
  104. "libnvidia-encode-${pkgver_major}"
  105. "libnvidia-fbc1-${pkgver_major}"
  106. "libnvidia-ifr1-${pkgver_major}"
  107. "nvidia-compute-utils-${pkgver_major}"
  108. "nvidia-utils-${pkgver_major}"
  109. )
  110. ########################################################
  111. pkgver_sed=$(printf '%s' ${pkgver} | sed 's/\./\\\./')
  112. i=0
  113. for f in ${files[@]}; do
  114. file_basename=$(printf '%s' ${f} | awk -F / '{print $NF}')
  115. filebases[$i]=${file_basename}
  116. let i++
  117. done
  118. oldver=$(printf '%s' ${filebases[0]} | grep -oE "[0-9]{3}\.[0-9]{2}" | head -1)
  119. oldver_major=$(printf '%s' ${filebases[0]} | grep -oE "[0-9]{3}" | head -1)
  120. oldver_sed=$(printf '%s' ${oldver} | sed 's/\./\\\./')
  121. ########################################################
  122. # http://wiki.bash-hackers.org/snipplets/print_horizontal_line#a_line_across_the_entire_width_of_the_terminal
  123. function INFO_SEP() { printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - ; }
  124. ###########################################################
  125. echo -e "\n${SCRIPT_TITLE}\n"
  126. ########################################################
  127. echo -e "Selected driver version:\t${pkgver}\n"
  128. INFO_SEP
  129. ########################################################
  130. mkdir -p ${BUILD_MAINDIR}
  131. if [[ $? -eq 0 ]]; then
  132. cd ${BUILD_MAINDIR}
  133. WORKDIR=${PWD}
  134. else
  135. echo -e "Error: couldn't create Nvidia build directory. Aborting\n"
  136. exit 1
  137. fi
  138. ########################################################
  139. # If the script is interrupted (Ctrl+C/SIGINT), do the following
  140. function Nvidia_intCleanup() {
  141. rm -rf ${WORKDIR}/{${pkgdir}
  142. }
  143. # Allow interruption of the script at any time (Ctrl + C)
  144. trap "Nvidia_intCleanup && exit 0" INT
  145. # Error event
  146. #trap "Nvidia_intCleanup && exit 1" ERR
  147. # Remove old build files
  148. Nvidia_intCleanup
  149. ###########################################################
  150. COMMANDS=(
  151. apt
  152. dpkg
  153. grep
  154. sudo
  155. wc
  156. wget
  157. )
  158. function checkCommands() {
  159. local COMMANDS_NOTFOUND
  160. local a
  161. if [[ $(which --help 2>/dev/null) ]] && [[ $(echo --help 2>/dev/null) ]]; then
  162. a=0
  163. for command in ${@}; do
  164. if [[ ! $(which $command 2>/dev/null) ]]; then
  165. COMMANDS_NOTFOUND[$a]=${command}
  166. let a++
  167. fi
  168. done
  169. if [[ -n $COMMANDS_NOTFOUND ]]; then
  170. echo -e "\nError! The following commands could not be found: ${COMMANDS_NOTFOUND[*]}\nAborting\n"
  171. exit 1
  172. fi
  173. else
  174. exit 1
  175. fi
  176. }
  177. checkCommands "${COMMANDS[*]}"
  178. ########################################################
  179. # General function for question responses
  180. function questionresponse() {
  181. local response
  182. response=${1}
  183. read -r -p "" response
  184. if [[ $(echo $response | sed 's/ //g') =~ ^([yY][eE][sS]|[yY])$ ]]; then
  185. echo ""
  186. return 0
  187. else
  188. return 1
  189. fi
  190. }
  191. ########################################################
  192. # Premilinary check for already compiled packages
  193. if [[ $(ls ${WORKDIR}/*.deb 2>/dev/null | wc -l) -ne 0 ]]; then
  194. echo -e "\nWarning: previously compiled deb archives found on the main build directory '${WORKDIR}'.\nDelete them and continue? [Y/n]"
  195. questionresponse
  196. fi
  197. if [[ $? -ne 0 ]]; then
  198. echo -e "Cancelling.\n"
  199. exit 1
  200. else
  201. rm -rfv ${WORKDIR}/*.{deb,buildinfo,changes} 2>/dev/null
  202. fi
  203. ########################################################
  204. # Premilinary check to see whether Nvidia card is present
  205. if [[ ! $(lspci | grep -oiE "vga.*nvidia") ]]; then
  206. echo -e "\nWarning: Nvidia card could not be detected on your system. Continue anyway? [Y/n]"
  207. questionresponse
  208. fi
  209. if [[ $? -ne 0 ]]; then
  210. echo -e "Cancelling.\n"
  211. exit 1
  212. fi
  213. ########################################################
  214. # Auto-install question
  215. echo -e "\nAuto-install Nvidia drivers after compilation? [Y/n]"
  216. questionresponse
  217. if [[ $? -eq 0 ]]; then
  218. if [[ ${UID} -ne 0 ]]; then
  219. if [[ $(echo $(sudo -vn &>/dev/null)$?) -ne 0 ]]; then
  220. echo -e "NVIDIA driver installation requires root permissions. Please provide your sudo password now.\n"
  221. sudo -v
  222. fi
  223. if [[ $? -eq 0 ]]; then
  224. AUTOINSTALL=
  225. else
  226. exit 1
  227. fi
  228. else
  229. AUTOINSTALL=
  230. fi
  231. fi
  232. ########################################################
  233. function pkg_installcheck() {
  234. RETURNVALUE=$(echo $(dpkg -s "${1}" &>/dev/null)$?)
  235. return $RETURNVALUE
  236. }
  237. ########################################################
  238. # Check and install package related dependencies if they are missing
  239. function pkgdependencies() {
  240. local a
  241. local b
  242. # Generate a list of missing dependencies
  243. a=0
  244. for p in ${@}; do
  245. if [[ $(pkg_installcheck ${p}) -ne 0 ]]; then
  246. validlist[$a]=${p}
  247. let a++
  248. fi
  249. done
  250. if [[ -n ${validlist[*]} ]]; then
  251. echo -e "The following build time dependencies are missing. In order to continue, you must install them:\n$(for i in ${validlist[@]}; do echo ${i}; done)\n"
  252. if [[ ${UID} -ne 0 ]] && [[ $(echo $(sudo -vn &>/dev/null)$?) -ne 0 ]]; then
  253. echo -e "For that, sudo password is required. Please provide it now.\n"
  254. sudo -v
  255. if [[ $? -ne 0 ]]; then
  256. echo -e "Error: couldn't continue due to lacking permissions. Aborting\n"
  257. exit 1
  258. fi
  259. fi
  260. fi
  261. # Install missing dependencies, be informative
  262. b=0
  263. for pkgdep in ${validlist[@]}; do
  264. echo -e "$(( $b + 1 ))/$(( ${#validlist[*]} )) - Installing ${_pkgname} dependency ${pkgdep}"
  265. sudo apt install -y ${pkgdep} &> /dev/null
  266. if [[ $? -eq 0 ]]; then
  267. let b++
  268. else
  269. echo -e "\nError occured while installing ${pkgdep}. Aborting.\n"
  270. exit 1
  271. fi
  272. done
  273. }
  274. ########################################################
  275. function download_files() {
  276. mkdir -p ${WORKDIR}/${pkgdir}
  277. i=0
  278. for f in ${files[@]}; do
  279. if [[ ! -f ${WORKDIR}/${pkgdir}/${filebases[$i]} ]]; then
  280. echo ${f}
  281. echo -e "\nDownloading ${filebases[$i]}"
  282. wget ${f} -o /dev/null --show-progress -O "${WORKDIR}/${pkgdir}/${filebases[$i]}"
  283. if [[ $? -ne 0 ]];then
  284. echo -e "Error: couldn't retrieve file ${filebases[$i]}. Aborting\n"
  285. exit 1
  286. fi
  287. fi
  288. let i++
  289. done
  290. }
  291. ########################################################
  292. function prepare_deb_sources() {
  293. local oldlib_sed
  294. local lib_sed
  295. local oldlib_files
  296. local i
  297. # Extract debian control files
  298. cd ${WORKDIR}/${pkgdir}/
  299. tar xf ${filebases[0]}
  300. if [[ $? -eq 0 ]]; then
  301. function fix_library_versions() {
  302. for oldlib in ${!library_fixes[@]}; do
  303. # sed-friendly name
  304. oldlib_sed=$(printf '%s' ${oldlib} | sed 's/\./\\\./g')
  305. for lib in ${library_fixes[$oldlib]}; do
  306. # sed-friendly name
  307. lib_sed=$(printf '%s' ${lib} | sed 's/\./\\\./g')
  308. # Files which have old library files mentioned
  309. i=0
  310. for oldlib_file in $(grep -rl "${oldlib}" debian/ | tr '\n' ' '); do
  311. oldlib_files[$i]=${oldlib_file}
  312. let i++
  313. done
  314. for targetfile in ${oldlib_files[@]}; do
  315. sed -i "s/${oldlib_sed}/${lib_sed}/g" ${targetfile}
  316. done
  317. done
  318. done
  319. }
  320. function rename_deb_files() {
  321. local n_new
  322. local IFS
  323. # Remove this suffix
  324. sed -i 's/\-no\-compat32//' debian/rules.defs
  325. # Tell that Nvidia .run file is at our build root, not in amd64 subfolder
  326. sed -i 's|sh \$\*\/\${NVIDIA_FILENAME_\$\*}|sh \${NVIDIA_FILENAME_\$\*}|' debian/rules
  327. ############
  328. # TODO Individual fix for strange version number present in debian control files
  329. # Remove when not needed!
  330. sed -i "s/384/${pkgver_major}/g" debian/control
  331. sed -i "s/384/${pkgver_major}/g" debian/templates/control.in
  332. ############
  333. IFS=$'\n'
  334. for n in $(ls debian/ -w 1); do
  335. # IMPORTANT! KEEP THIS IF STATEMENT ORDER BELOW!!
  336. # Do this for every file in debian subfolder regardless of their name
  337. if [[ -f debian/${n} ]]; then
  338. # Keep this order. It is important!
  339. sed -i "s/${oldver_sed}/${pkgver_sed}/g" debian/${n}
  340. sed -i "s/${oldver_major}/${pkgver_major}/g" debian/${n}
  341. fi
  342. if [[ $(printf '%s' ${n} | grep ${oldver_major}) ]]; then
  343. n_new=$(printf '%s' ${n} | sed "s/${oldver_major}/${pkgver_major}/")
  344. mv debian/${n} debian/${n_new}
  345. if [[ $? -ne 0 ]]; then
  346. echo -e "Error: couldn't rename file debian/${n}. Aborting\n"
  347. exit 1
  348. fi
  349. fi
  350. done
  351. unset IFS
  352. }
  353. fix_library_versions
  354. rename_deb_files
  355. else
  356. echo -e "Error: couldn't extract Nvidia Debian archive. Aborting\n"
  357. exit 1
  358. fi
  359. }
  360. ########################################################
  361. function compile_nvidia() {
  362. cd ${WORKDIR}/${pkgdir}/
  363. DEB_BUILD_OPTIONS="strip noddebs" dpkg-buildpackage -rfakeroot -b -us -uc
  364. if [[ $? -eq 0 ]]; then
  365. mkdir -p ${WORKDIR}/compiled_deb
  366. for p in ${nvidia_install_packages[*]}; do
  367. mv ${WORKDIR}/${p}*.deb ${WORKDIR}/compiled_deb/
  368. done
  369. if [[ $? -eq 0 ]]; then
  370. echo -e "Compiled deb packages moved into '${WORKDIR}/compiled_deb/'. Install these to enable Nvidia support.\nAdditionally, you may need Vulkan loader package 'libvulkan1', too.\n"
  371. else
  372. echo -e "Error: couldn't move deb packages into '${WORKDIR}/compiled_deb/'. Aborting\n"
  373. exit 1
  374. fi
  375. mkdir -p ${WORKDIR}/compiled_other
  376. for a in ${WORKDIR}/*; do
  377. if [[ -f ${a} ]]; then
  378. mv ${a} ${WORKDIR}/compiled_other/
  379. fi
  380. done
  381. if [[ $? -eq 0 ]]; then
  382. echo -e "Other files moved into '${WORKDIR}/compiled_other/' \n"
  383. else
  384. echo -e "Error: couldn't move other files into '${WORKDIR}/compiled_other/'. Aborting\n"
  385. exit 1
  386. fi
  387. else
  388. echo -e "Error: couldn't compile Nvidia package bundle. Aborting\n"
  389. exit 1
  390. fi
  391. }
  392. ########################################################
  393. function install_nvidia() {
  394. local oldpkg
  395. local oldpkg_check
  396. for syspkg in ${nvidia_required_packages[@]}; do
  397. if [[ $(echo $(dpkg -s ${syspkg} &>/dev/null)$?) -ne 0 ]]; then
  398. echo -e "Installing missing dependency ${syspkg}\n"
  399. sudo apt install -y ${syspkg}
  400. if [[ $? -ne 0 ]]; then
  401. echo -e "Error: couldn't install dependency ${syspkg}. Aborting\n"
  402. exit 1
  403. fi
  404. fi
  405. done
  406. cd ${WORKDIR}/compiled_deb
  407. for pkg in ${nvidia_install_packages[@]}; do
  408. oldpkg=$(printf '%s' ${pkg} | sed 's/\-[0-9]*$//')
  409. oldpkg_check=$(dpkg --get-selections | grep ${oldpkg} | awk '{print $1}')
  410. if [[ $(echo ${oldpkg_check} | wc -w) -eq 1 ]]; then
  411. if [[ ! ${oldpkg_check} =~ ^*${pkgver_major}$ ]]; then
  412. echo -e "Removing old ${oldpkg}\n"
  413. sudo apt purge --remove -y "${oldpkg}*"
  414. if [[ $? -ne 0 ]]; then
  415. echo -e "Error: couldn't uninstall ${oldpkg}. Aborting\n"
  416. exit 1
  417. fi
  418. fi
  419. fi
  420. echo -e "Installing ${pkg}\n"
  421. sudo dpkg -i ${pkg}*.deb
  422. if [[ $? -ne 0 ]]; then
  423. echo -e "Warning: couldn't install ${pkg}\n"
  424. fi
  425. done
  426. }
  427. function install_vulkan() {
  428. local syspkg
  429. # Vulkan loader
  430. if [[ $? -eq 0 ]]; then
  431. syspkg=libvulkan1
  432. if [[ $(echo $(dpkg -s ${syspkg} &>/dev/null)$?) -ne 0 ]]; then
  433. sudo apt update && sudo apt install -y ${syspkg}
  434. fi
  435. fi
  436. }
  437. ########################################################
  438. pkgdependencies ${nvidia_builddeps[*]} && \
  439. download_files && \
  440. prepare_deb_sources && \
  441. compile_nvidia
  442. if [[ $? -eq 0 ]] && [[ -v AUTOINSTALL ]]; then
  443. install_nvidia && \
  444. install_vulkan
  445. fi
  446. # If any buildtime deps were installed, inform the user
  447. if [[ -n ${validlist[*]} ]]; then
  448. echo -e "The following buildtime dependencies were installed, and they may not be required anymore:\n\n\
  449. $(for h in ${validlist[*]}; do echo ${h}; done)\n"
  450. fi