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.

620 lines
18 KiB

6 years ago
6 years ago
  1. #!/bin/env bash
  2. # Compile DXVK git on Debian/Ubuntu/Mint and variants
  3. # Copyright (C) 2018 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. # DO NOT RUN INDIVIDUALLY, ONLY VIA ../../updatewine.sh PARENT SCRIPT!
  19. ########################################################
  20. # Root directory of this script file
  21. DXVKROOT="${PWD}"
  22. # datedir variable supplied by ../updatewine_debian.sh script file
  23. datedir="${1}"
  24. ###########################################################
  25. # Parse input arguments
  26. i=0
  27. for arg in ${@:2}; do
  28. args[$i]="${arg}"
  29. let i++
  30. done
  31. # Must be a true array as defined above, not a single index list!
  32. #args="${@:2}"
  33. for check in ${args[@]}; do
  34. case ${check} in
  35. --no-install)
  36. NO_INSTALL=
  37. ;;
  38. --updateoverride)
  39. UPDATE_OVERRIDE=
  40. ;;
  41. --buildpkg-rm)
  42. BUILDPKG_RM=
  43. ;;
  44. esac
  45. done
  46. ###########################################################
  47. # Check presence of Wine. Some version of Wine should
  48. # be found in the system in order to install DXVK.
  49. known_wines=(
  50. 'wine'
  51. 'wine-stable'
  52. 'wine32'
  53. 'wine64'
  54. 'libwine:amd64'
  55. 'libwine:i386'
  56. 'wine-git'
  57. 'wine-staging-git'
  58. )
  59. known_winetricks=(
  60. 'winetricks'
  61. )
  62. function runtimeCheck() {
  63. # Friendly name for this package
  64. local pkgreq_name=${1}
  65. # Known package names to check on Debian
  66. local known_pkgs=${2}
  67. # Check if any of these Wine packages are present on the system
  68. i=0
  69. for pkg in ${known_pkgs[@]}; do
  70. if [[ $(echo $(dpkg -s ${pkg} &>/dev/null)$?) -eq 0 ]]; then
  71. local pkglist[$i]=${pkg}
  72. let i++
  73. fi
  74. done
  75. if [[ -z ${pkglist[*]} ]]; then
  76. echo -e "\e[1mWARNING:\e[0m Not installing DXVK because \e[1m${pkgreq_name}\e[0m is missing on your system.\n\
  77. ${pkgreq_name} should be installed in order to use DXVK. Just compiling DXVK for later use.\n"
  78. # Do this check separately so we can warn about all missing runtime dependencies above
  79. if [[ ! -v NO_INSTALL ]]; then
  80. # Force --no-install switch
  81. NO_INSTALL=
  82. fi
  83. fi
  84. }
  85. # Check existence of known Wine packages
  86. runtimeCheck Wine "${known_wines[*]}"
  87. # Check existence of known Winetricks packages
  88. runtimeCheck Winetricks "${known_winetricks[*]}"
  89. ###########################################################
  90. # If the script is interrupted (Ctrl+C/SIGINT), do the following
  91. function DXVK_intCleanup() {
  92. rm -rf ${DXVKROOT}/{dxvk-git,meson,glslang}
  93. rm -rf ${DXVKROOT}/../compiled_deb/"${datedir}"
  94. exit 0
  95. }
  96. # Allow interruption of the script at any time (Ctrl + C)
  97. trap "DXVK_intCleanup" INT
  98. ########################################################
  99. # http://wiki.bash-hackers.org/snipplets/print_horizontal_line#a_line_across_the_entire_width_of_the_terminal
  100. function INFO_SEP() { printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - ; }
  101. ##################################
  102. # Update all packages if UPDATE_OVERRIDE given
  103. if [[ -v UPDATE_OVERRIDE ]]; then
  104. echo -en "Updating all packages" && \
  105. if [[ $(printf $(sudo -n uptime &>/dev/null)$?) -ne 0 ]]; then printf " Please provide your sudo password.\n"; else printf "\n\n"; fi
  106. sudo apt update && sudo apt upgrade -y
  107. fi
  108. ##################################
  109. # Check do we need to compile the package
  110. # given as input for this function
  111. function pkgcompilecheck() {
  112. local pkg=${1}
  113. local install_function=${2}
  114. if [[ $(echo $(dpkg -s ${pkg} &>/dev/null)$?) -ne 0 ]] || [[ -v UPDATE_OVERRIDE ]]; then
  115. ${install_function}
  116. fi
  117. }
  118. ###################################################
  119. # Global variable to track buildtime dependencies
  120. z=0
  121. function preparepackage() {
  122. # Set local variables
  123. local _pkgname=${1}
  124. local _pkgdeps_build=${2}
  125. local _pkgurl=${3}
  126. local _pkgver=${4}
  127. echo -e "Starting compilation$(if [[ ! -v NO_INSTALL ]] || [[ ${_pkgname} =~ ^meson|glslang$ ]]; then printf " & installation"; fi) of ${1}\n"
  128. # Optional variable for runtime dependencies array
  129. if [[ -n ${5} ]]; then local _pkgdeps_runtime=${5}; fi
  130. # Check and install package related dependencies if they are missing
  131. function pkgdependencies() {
  132. local pkglist="${1}"
  133. local pkgtype="${2}"
  134. # Generate a list of missing dependencies
  135. local a=0
  136. for p in ${pkglist[@]}; do
  137. if [[ $(echo $(dpkg -s ${p} &>/dev/null)$?) -ne 0 ]]; then
  138. local validlist[$a]=${p}
  139. let a++
  140. # Global array to track installed build dependencies
  141. if [[ ${pkgtype} == "buildtime" ]]; then
  142. buildpkglist[$z]=${p}
  143. let z++
  144. fi
  145. fi
  146. done
  147. # Install missing dependencies, be informative
  148. local b=0
  149. for pkgdep in ${validlist[@]}; do
  150. echo -e "$(( $b + 1 ))/$(( ${#validlist[*]} )) - Installing ${_pkgname} dependency ${pkgdep}"
  151. sudo apt install -y ${pkgdep} &> /dev/null
  152. if [[ $? -eq 0 ]]; then
  153. let b++
  154. else
  155. echo -e "\nError occured while installing ${pkgdep}. Aborting.\n"
  156. exit 1
  157. fi
  158. done
  159. if [[ -n ${validlist[*]} ]]; then
  160. # Add empty newline
  161. echo ""
  162. fi
  163. }
  164. # Get git-based version in order to rename the package main folder
  165. # This is required by deb builder. It retrieves the version number
  166. # from that folder name
  167. function pkgversion() {
  168. if [[ -n "${_pkgver}" ]] && [[ "${_pkgver}" =~ ^git ]]; then
  169. cd ${_pkgname}
  170. _pkgver=$(eval "${_pkgver}")
  171. cd ..
  172. fi
  173. }
  174. function pkgfoldername() {
  175. # Remove old build directory, if present
  176. rm -rf ${_pkgname}
  177. # Create a new build directory, access it and download git sources there
  178. mkdir ${_pkgname}
  179. cd ${_pkgname}
  180. echo -e "Retrieving source code of ${_pkgname} from $(printf ${_pkgurl} | sed 's/^.*\/\///; s/\/.*//')\n"
  181. git clone ${_pkgurl} ${_pkgname}
  182. # If sources could be downloaded, rename the folder properly for deb builder
  183. # Access the folder after which package specific debianbuild function will be run
  184. # That function is defined inside package specific install_main function below
  185. if [[ $? -eq 0 ]]; then
  186. pkgversion && \
  187. mv ${_pkgname} ${_pkgname}-${_pkgver}
  188. cd ${_pkgname}-${_pkgver}
  189. else
  190. echo -e "Error while downloading source of ${_pkgname} package. Aborting\n"
  191. exit 1
  192. fi
  193. }
  194. # Execute above functions
  195. pkgdependencies "${_pkgdeps_build[*]}" buildtime && \
  196. if [[ -v _pkgdeps_runtime ]]; then pkgdependencies "${_pkgdeps_runtime[*]}" runtime ; fi
  197. pkgfoldername
  198. unset _pkgver
  199. }
  200. ###################################################
  201. # BUILD DEPENDENCIES REMOVAL
  202. function buildpkg_removal() {
  203. # Build time dependencies which were installed but no longer needed
  204. if [[ -v buildpkglist ]]; then
  205. if [[ -v BUILDPKG_RM ]]; then
  206. sudo apt purge --remove -y "${buildpkglist[*]}"
  207. # In some cases, glslang or meson may still be present on the system. Remove them
  208. for extrapkg in glslang meson; do
  209. if [[ $(echo $(dpkg -s ${extrapkg} &>/dev/null)$?) -eq 0 ]]; then
  210. sudo apt purge --remove -y ${extrapkg}
  211. fi
  212. done
  213. else
  214. echo -e "The following build time dependencies were installed and no longer needed:\n\n$(for l in ${buildpkglist[*]}; do echo -e ${l}; done)\n"
  215. fi
  216. fi
  217. }
  218. ###################################################
  219. # MESON COMPILATION & INSTALLATION
  220. # Required by DXVK package
  221. function meson_install_main() {
  222. # Package name
  223. local pkgname="meson"
  224. # Build time dependencies
  225. local pkgdeps_build=(
  226. 'python3'
  227. 'dh-python'
  228. 'python3-setuptools'
  229. 'ninja-build'
  230. )
  231. # Git source location
  232. local pkgurl="https://github.com/mesonbuild/meson"
  233. # Parsed version number from git source files
  234. local pkgver_git="git describe --long | sed 's/\-[a-z].*//; s/\-/\./; s/[a-z]//g'"
  235. # Location of Debian compilation instructions archive
  236. local pkgurl_debian="http://archive.ubuntu.com/ubuntu/pool/universe/m/meson/meson_0.45.1-2.debian.tar.xz"
  237. function meson_debianbuild() {
  238. # Download predefined Meson debian rules archive
  239. # Extract it, and finally delete the archive
  240. wget ${pkgurl_debian} -O debian.tar.xz
  241. tar xf debian.tar.xz && rm debian.tar.xz
  242. # Get sed compatible Meson version string
  243. local meson_version=$(printf '%s' $(pwd | sed -e 's/.*\-//' -e 's/\./\\\./g'))
  244. # Do not perform any tests or checks during compilation process
  245. sed -ir '/nocheck/d' debian/control
  246. sed -ir '/\.\/run_tests\.py/d' debian/rules
  247. # Downgrade debhelper version requirement for Debian compatilibity
  248. sed -ir 's/debhelper (>= 11)/debhelper (>= 10)/' debian/control
  249. # Correct & update package version number + debian rules
  250. sed -ir "s/0\.45\.1-2/${meson_version}/" debian/changelog
  251. # Delete the following strings from debian/rules file
  252. # They are deprecated
  253. sed -ir '/rm \$\$(pwd)\/debian\/meson\/usr\/bin\/mesontest/d' debian/rules
  254. sed -ir '/rm \$\$(pwd)\/debian\/meson\/usr\/bin\/mesonconf/d' debian/rules
  255. sed -ir '/rm \$\$(pwd)\/debian\/meson\/usr\/bin\/mesonintrospect/d' debian/rules
  256. sed -ir '/rm \$\$(pwd)\/debian\/meson\/usr\/bin\/wraptool/d' debian/rules
  257. sed -ir '/rm \-rf \$\$(pwd)\/debian\/meson\/usr\/lib\/python3/d' debian/rules
  258. # Remove deprecated, downloaded patch files
  259. rm -rf debian/patches
  260. # Remove irrelevant sample files
  261. rm -rf debian/*.{ex,EX}
  262. # Start deb builder. Do not build either debug symbols or doc files
  263. DEB_BUILD_OPTIONS="strip nodocs noddebs nocheck" dpkg-buildpackage -rfakeroot -b -us -uc
  264. # Once compiled, install and store the compiled deb archive
  265. # We do not make installation optional because this is a core dependency for DXVK
  266. if [[ $? -eq 0 ]]; then
  267. rm -rf ../*.{changes,buildinfo,tar.xz} && \
  268. sudo dpkg -i ../${pkgname}*.deb && \
  269. mv ../${pkgname}*.deb ../../../compiled_deb/"${datedir}" && \
  270. echo -e "Compiled ${pkgname} is stored at '$(readlink -f ../../../compiled_deb/"${datedir}")/'\n"
  271. cd ../..
  272. rm -rf ${pkgname}
  273. else
  274. exit 1
  275. fi
  276. }
  277. # Execute above functions
  278. preparepackage "${pkgname}" "${pkgdeps_build[*]}" "${pkgurl}" "${pkgver_git}" && \
  279. meson_debianbuild
  280. }
  281. ###################################################
  282. # GLSLANG COMPILATION & INSTALLATION
  283. # Required by DXVK package
  284. function glslang_install_main() {
  285. # Package name
  286. local pkgname="glslang"
  287. # Build time dependencies
  288. local pkgdeps_build=('cmake' 'python2.7')
  289. # Git source location
  290. local pkgurl="https://github.com/KhronosGroup/glslang"
  291. # Parsed version number from git source files
  292. local pkgver_git="git describe --long | sed 's/\-[a-z].*//; s/\-/\./; s/[a-z]//g'"
  293. function glslang_debianbuild() {
  294. # Create debian subdirectory
  295. dh_make --createorig -s -y -c bsd
  296. # Set Build dependencies into debian/control file
  297. sed -ie "s/^Build-Depends:.*$/Build-Depends: debhelper (>=10), $(echo ${_coredeps[*]} | \
  298. sed 's/\s/, /g'), $(echo ${pkgdeps_build[*]} | sed 's/\s/, /g')/g" debian/control
  299. # Skip running override_dh_usrlocal while executing deb builder
  300. printf 'override_dh_usrlocal:' | tee -a debian/rules
  301. # Remove irrelevant sample files
  302. rm -rf debian/*.{ex,EX}
  303. # Start deb builder. Do not build either debug symbols or doc files
  304. DEB_BUILD_OPTIONS="strip nodocs noddebs" dpkg-buildpackage -rfakeroot -b -us -uc
  305. # Once compiled, install and store the compiled deb archive
  306. # We do not make installation optional because this is a core dependency for DXVK
  307. if [[ $? -eq 0 ]]; then
  308. rm -rf ../*.{changes,buildinfo,tar.xz} && \
  309. sudo dpkg -i ../${pkgname}*.deb && \
  310. mv ../${pkgname}*.deb ../../../compiled_deb/"${datedir}" && \
  311. echo -e "Compiled ${pkgname} is stored at '$(readlink -f ../../../compiled_deb/"${datedir}")/'\n"
  312. cd ../..
  313. rm -rf ${pkgname}
  314. else
  315. # If we fail to build DXVK, remove possibly compiled & installed meson + glslang packages
  316. buildpkg_removal
  317. exit 1
  318. fi
  319. }
  320. # Execute above functions
  321. preparepackage "${pkgname}" "${pkgdeps_build[*]}" "${pkgurl}" "${pkgver_git}" && \
  322. glslang_debianbuild
  323. }
  324. ###################################################
  325. # DXVK COMPILATION & INSTALLATION
  326. function dxvk_install_main() {
  327. # Package name
  328. local pkgname="dxvk-git"
  329. # Build time dependencies
  330. local pkgdeps_build=(
  331. 'meson'
  332. 'glslang'
  333. 'gcc-mingw-w64-x86-64'
  334. 'gcc-mingw-w64-i686'
  335. 'g++-mingw-w64-x86-64'
  336. 'g++-mingw-w64-i686'
  337. 'mingw-w64-x86-64-dev'
  338. 'mingw-w64-i686-dev'
  339. )
  340. # Runtime dependencies
  341. local pkgdeps_runtime=('wine' 'winetricks')
  342. # Git source location
  343. local pkgurl="https://github.com/doitsujin/dxvk"
  344. # Parsed version number from git source files
  345. local pkgver_git="git describe --long | sed 's/\-[a-z].*//; s/\-/\./; s/[a-z]//g'"
  346. # Use posix alternates for MinGW binaries
  347. function dxvk_posixpkgs() {
  348. local packages=(
  349. 'i686-w64-mingw32-g++'
  350. 'i686-w64-mingw32-gcc'
  351. 'x86_64-w64-mingw32-g++'
  352. 'x86_64-w64-mingw32-gcc'
  353. )
  354. for package in "${packages[@]}"; do
  355. local option=$(echo "" | sudo update-alternatives --config "${package}" | grep posix | sed 's@^[^0-9]*\([0-9]\+\).*@\1@')
  356. echo "${option}" | sudo update-alternatives --config "${package}" &> /dev/null
  357. if [[ $? -ne 0 ]]; then
  358. echo -e "Error occured while running 'update-alternatives' for '${package}'. Aborting\n"
  359. exit 1
  360. fi
  361. done
  362. }
  363. function dxvk_custompatches() {
  364. # Get our current directory, since we will change it during patching process below
  365. # We want to go back here after having applied the patches
  366. local CURDIR=${PWD}
  367. # Check if the following folder exists, and proceed.
  368. if [[ -d ${DXVKROOT}/../../dxvk_custom_patches ]]; then
  369. cp -r ${DXVKROOT}/../../dxvk_custom_patches/*.{patch,diff} ${DXVKROOT}/${pkgname}/ 2>/dev/null
  370. local dxvk_builddir_name=$(ls ${DXVKROOT}/${pkgname}/)
  371. # TODO Expecting just one folder here. This method doesn't work with multiple dirs present
  372. if [[ $(echo ${dxvk_builddir_name} | wc -l) -gt 1 ]]; then
  373. echo "Error: Multiple entries in dxvk build directory detected. Can't decide which one to use. Aborting\n"
  374. exit 1
  375. fi
  376. local dxvk_builddir_path="${DXVKROOT}/${pkgname}/${dxvk_builddir_name}"
  377. cd "${dxvk_builddir_path}"
  378. for pfile in ../*.{patch,diff}; do
  379. if [[ -f ${pfile} ]]; then
  380. echo -e "Applying DXVK patch: ${pfile}\n"
  381. patch -Np1 < ${pfile}
  382. fi
  383. if [[ $? -ne 0 ]]; then
  384. echo -e "Error occured while applying DXVK patch '${pfile}'. Aborting\n"
  385. cd ${CURDIR}
  386. exit 1
  387. fi
  388. done
  389. cd ${CURDIR}
  390. fi
  391. }
  392. # Debian-specific compilation & installation rules
  393. function dxvk_debianbuild() {
  394. local dxvx_relative_builddir="debian/source/dxvk-master"
  395. # Create debian subdirectory, add supplied LICENSE file
  396. dh_make --createorig -s -y -c custom --copyrightfile ../LICENSE
  397. # Set Build dependencies into debian/control file
  398. sed -ie "s/^Build-Depends:.*$/Build-Depends: debhelper (>=10), $(echo ${_coredeps[*]} | \
  399. sed 's/\s/, /g'), $(echo ${pkgdeps_build[*]} | sed 's/\s/, /g')/g" debian/control
  400. # Set Runtime dependencies into debian/control file
  401. sed -ie "s/^Depends:.*$/Depends: $(echo ${pkgdeps_runtime} | sed 's/\s/, /g')/g" debian/control
  402. # Tell deb builder to bundle these files
  403. printf "${dxvx_relative_builddir}/setup_dxvk.verb usr/share/dxvk/" > debian/install
  404. printf "\n${dxvx_relative_builddir}/bin/* usr/bin/" >> debian/install
  405. # Remove irrelevant sample files
  406. rm -rf debian/*.{ex,EX}
  407. # Overwrite debian/rules file with the following contents
  408. cat << 'DXVK-DEBIANRULES' > debian/rules
  409. #!/usr/bin/make -f
  410. %:
  411. dh $@
  412. override_dh_auto_configure:
  413. override_dh_usrlocal:
  414. DXVK-DEBIANRULES
  415. # Start DXVK compilation
  416. bash ./package-release.sh master debian/source/ --no-package
  417. if [[ $? -ne 0 ]]; then
  418. echo -e "Error while compiling ${pkgname}. Check messages above. Aborting\n"
  419. buildpkg_removal
  420. exit 1
  421. fi
  422. # Make a proper executable script for setup_dxvk.verb file
  423. mkdir -p ${dxvx_relative_builddir}/bin
  424. echo -e "#!/bin/sh\nwinetricks --force /usr/share/dxvk/setup_dxvk.verb" \
  425. > "${dxvx_relative_builddir}/bin/setup_dxvk"
  426. chmod +x "${dxvx_relative_builddir}/bin/setup_dxvk"
  427. # Tell deb builder to install DXVK x32 & x64 subfolders
  428. for arch in 64 32; do
  429. mkdir -p ${dxvx_relative_builddir}/x${arch}
  430. printf "\n${dxvx_relative_builddir}/x${arch}/* usr/share/dxvk/x${arch}/" >> debian/install
  431. done
  432. # Start deb builder. Do not build either debug symbols or doc files
  433. DEB_BUILD_OPTIONS="strip nodocs noddebs" dpkg-buildpackage -us -uc -b --source-option=--include-binaries
  434. # Once compiled, possibly install and store the compiled deb archive
  435. if [[ $? -eq 0 ]]; then
  436. if [[ ! -v NO_INSTALL ]]; then
  437. sudo dpkg -i ../${pkgname}*.deb
  438. fi
  439. rm -rf ../*.{changes,buildinfo,tar.xz}
  440. mv ../${pkgname}*.deb ../../../compiled_deb/"${datedir}" && \
  441. echo -e "Compiled ${pkgname} is stored at '$(readlink -f ../../../compiled_deb/"${datedir}")/'\n"
  442. cd ../..
  443. rm -rf ${pkgname}
  444. else
  445. exit 1
  446. fi
  447. }
  448. # Execute above functions
  449. # Do not check runtime dependencies as our check method expects exact package name in
  450. # function 'preparepackage'. This does not apply to runtime dependency 'wine', which
  451. # may be 'wine', 'wine-git', 'wine-staging-git' etc. in truth
  452. #
  453. preparepackage "${pkgname}" "${pkgdeps_build[*]}" "${pkgurl}" "${pkgver_git}" && \
  454. dxvk_posixpkgs && \
  455. dxvk_custompatches && \
  456. dxvk_debianbuild
  457. }
  458. ####################################################################
  459. pkgcompilecheck meson meson_install_main
  460. pkgcompilecheck glslang glslang_install_main
  461. dxvk_install_main
  462. buildpkg_removal