Building Mesa from source

From GamingOnLinux.com Linux Games Wiki
Jump to: navigation, search

There are times when Mesa introduces some new feature that didn't yet make it into your distro. Some games can become playable with that change, or it can be simply a performance optimization that speeds up already working games - either way, you might be interested in running such latest development version of Mesa for various reasons. At the same time you don't want to mess up your system with unstable graphics stack. This guide will explain how to use such Mesa for playing games while keeping your system Mesa intact.

Note: This process has distro specific parts. You'd need to adapt it, to use with another distro. Feel free to expand this guide with a section which describes how you did it on your distro of choice.

Building Mesa on Debian testing

You probably want to build both 64-bit and 32-bit Mesa libraries, since the later are needed for 32-bit applications, including many older games, especially those run through Wine.

64-bit

First install various development tools and dependencies. Note: keep track of any installed / removed packages (copy them from apt-get lists for NEW and save in some file). You don't want to clutter, and let alone mess up your system. After you finished building all you need (both 64-bit and 32-bit), it's a good idea to return the system to the previous state. I.e. remove all the packages that got installed. To keep things tidy, you can do this whole thing inside a VM, which you can simply discard once you are done. This will avoid any risk of messing up your main system installation.

sudo apt-get install build-essential git
sudo apt-get build-dep mesa

Make / select yourself some directory (let's say $HOME/build) and start working from there. Clone the repo and prepare to configure it. This guide assumes using latest master branch. If you want to build a specific version instead of using master, you'd need to switch to it using git once it's cloned

mkdir -p $HOME/build
cd $HOME/build
git clone git://anongit.freedesktop.org/mesa/mesa
cd mesa
autoreconf -vfi

Now, you need to configure Mesa. There are multitude of ways to do it. Since I was building for Debian, I checked how the official distro package is configured. An easy way to do it is to first open Debian tracker page for Mesa. From there find the link "buildd: logs". Once on that page, find the row with amd64 architecture, and click on "Installed" which will open a full Debian build log for the package (you can also select Debian type, such as sid for unstable here, or anything else). Once in the log, find string /configure. That would take you right away to configuration part. Copy that string and analyze it if you want.

I adjusted it a bit. For example I planned to install resulted libraries in /opt/mesa-master. So I changed --prefix=/usr to --prefix=/opt/mesa-master. And to simplify things, --libdir=\${prefix}/lib/x86_64-linux-gnu --libexecdir=\${prefix}/lib/x86_64-linux-gnu to --libdir=\${prefix}/x86_64 --libexecdir=\${prefix}/x86_64 (note the explicit directory for x86_64, that's because afterwards, same process will be repeated for 32-bit build).

Also, you can remove some drivers from the list which you don't need to speed up compilation. That's up to you what to pick. I changed: --with-dri-drivers= nouveau i915 i965 r200 radeon to --with-dri-drivers= nouveau i965 and --with-gallium-drivers= nouveau svga virgl r600 r300 radeonsi swrast to --with-gallium-drivers= nouveau svga virgl radeonsi swrast. That's it, run the resulting configure command:

./configure --build=x86_64-linux-gnu --prefix=/opt/mesa-master --includedir=\${prefix}/include --mandir=\${prefix}/share/man --infodir=\${prefix}/share/info --sysconfdir=/etc --localstatedir=/var --disable-silent-rules --libdir=\${prefix}/x86_64 --libexecdir=\${prefix}/x86_64 --disable-maintainer-mode --disable-dependency-tracking --enable-dri "--with-dri-drivers= nouveau i965" --with-dri-driverdir=/usr/lib/x86_64-linux-gnu/dri --with-dri-searchpath=/usr/lib/x86_64-linux-gnu/dri:\\\$\${ORIGIN}/dri:/usr/lib/dri "--with-vulkan-drivers= intel radeon" --enable-osmesa --enable-glx-tls --enable-shared-glapi --enable-texture-float --disable-xvmc --disable-omx --enable-driglx-direct --enable-dri3 "--with-egl-platforms=x11 wayland drm" --enable-xa --enable-opencl --enable-opencl-icd --enable-gallium-llvm ac_cv_path_LLVM_CONFIG=llvm-config-3.9 --enable-vdpau --enable-va --enable-gallium-extra-hud --enable-lmsensors "--with-gallium-drivers= nouveau svga virgl radeonsi swrast" --enable-gles1 --enable-gles2 "CFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong -Wformat -Werror=format-security -Wall" "CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2" "CXXFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong -Wformat -Werror=format-security -Wall" "FCFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong" "FFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong" "GCJFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong" LDFLAGS=-Wl,-z,relro "OBJCFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong -Wformat -Werror=format-security" "OBJCXXFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong -Wformat -Werror=format-security"

If all is correct, it will succeed and Mesa is ready for building (change make parallelism with -j parameter according to your processor for faster compilation, in general you should put in the number of CPU cores you have):

make -j$(nproc)

After it's all built, publish the result to your target directory (in my case /opt/mesa-master):

mv -v x86_64/gallium/* x86_64/
rmdir x86_64/gallium

sudo mkdir /opt/mesa-master
sudo mv -v x86_64 /opt/mesa-master/
sudo cp src/intel/vulkan/intel_icd.x86_64.json /opt/mesa-master/x86_64/
sudo cp src/amd/vulkan/radeon_icd.x86_64.json /opt/mesa-master/x86_64/
sudo chown -R root:root /opt/mesa-master

Now you are ready to test your freshly built Mesa.

OpenGL:

LD_LIBRARY_PATH=/opt/mesa-master/x86_64:$LD_LIBRARY_PATH LIBGL_DRIVERS_PATH=/opt/mesa-master/x86_64 EGL_DRIVERS_PATH=/opt/mesa-master/x86_64 glxinfo | grep string

You'll get something like:

...
OpenGL renderer string: Gallium 0.4 on AMD POLARIS10 (DRM 3.3.0 / 4.8.0-2-amd64, LLVM 3.9.1)
OpenGL core profile version string: 4.5 (Core Profile) Mesa 17.0.0-devel (git-e9a4ec4bd8)
OpenGL core profile shading language version string: 4.50
OpenGL version string: 3.0 Mesa 17.0.0-devel (git-e9a4ec4bd8)
...

Vulkan:

LD_LIBRARY_PATH=/opt/mesa-master/x86_64:$LD_LIBRARY_PATH VK_ICD_FILENAMES=/opt/mesa-master/x86_64/radeon_icd.x86_64.json vulkaninfo | more
===========
VULKAN INFO
===========

Vulkan API Version: 1.0.37

INFO: [loader] Code 0 : Found manifest file /opt/mesa-master/x86_64/radeon_icd.x86_64.json, version "1.0.0"

Instance Extensions:
====================
Instance Extensions     count = 5
        VK_KHR_surface                      : extension revision 25
        VK_KHR_xcb_surface                  : extension revision  6
        VK_KHR_xlib_surface                 : extension revision  6
        VK_KHR_wayland_surface              : extension revision  5
        VK_EXT_debug_report                 : extension revision  4
WARNING: radv is not a conformant vulkan implementation, testing use only.
...
  • Note the environment variables needed to point the application to the custom driver. You'd need to set those for any game you want to run with this Mesa.
  • In the Vulkan example I assume radv (AMD) usage. If you are using Intel, change VK_ICD_FILENAMES=/opt/mesa-master/x86_64/radeon_icd.x86_64.json to VK_ICD_FILENAMES=/opt/mesa-master/x86_64/intel_icd.x86_64.json.
  • To run some Vulkan demos (to test if the driver even works), you can use builds from here. For example Viking Village demo has both 32-bit and 64-bit versions, so you can test both builds of the driver with it.

32-bit

After you are done with 64-bit, clean your build:

make clean
autoreconf -vfi

Using the above trick with sudo apt-get build-dep mesa wouldn't work for 32-bit (you could in theory try adding -a i386 to that command), because not all needed packages support multiarch in Debian yet. Configuration and building steps will fail however if all needed dependencies are not installed. You can figure them out one by one (this stuff can change in the future), by simply not installing anything first and running configure and then make. Analyzing errors you can figure out what packages are needed. This is a bit tedious, here is what I had to do:

sudo apt-get purge llvm-3.9 llvm-3.9-dev llvm-3.9-runtime libclang1-3.9 libclang-3.9-dev libclang-common-3.9-dev libgcrypt20-dev libgpg-error-dev libsensors4-dev

sudo apt-get install gcc-multilib g++-multilib libdrm-dev:i386 libexpat1-dev:i386 libxcb-dri3-dev:i386 libxcb-present-dev:i386 libxshmfence-dev:i386 libxext-dev:i386 libxdamage-dev:i386 libx11-xcb-dev:i386 libxcb-glx0-dev:i386 libxcb-dri2-0-dev:i386 libxxf86vm-dev:i386 libwayland-dev:i386 libsensors4-dev:i386 libclang-3.9-dev:i386 libclang1-3.9:i386 libgcrypt20-dev:i386 libgpg-error-dev:i386 llvm-3.9-dev:i386 libelf-dev:i386

Note, that some packages are not multilib compatible yet, so they'll try to remove their 64-bit counterparts. That's why to resolve some conflicts, you need to explicitly purge them first, like above. Here are some examples:

  • libsensors4-dev:i386 doesn't support multilib - removes libsensors4-dev (64-bit).
  • llvm-3.9-dev:i386 doesn't support multilib - removes llvm-3.9 llvm-3.9-dev llvm-3.9-runtime (64-bit).
  • libclang-3.9-dev:i386 doesn't support multilib - removes libclang-3.9-dev libclang-common-3.9-dev (64-bit).
  • libgcrypt20-dev:i386 doesn't support multilib - removes ibgcrypt20-dev libgpg-error-dev (64-bit).

I had to restore some stuff after that, such as llvm-3.9 llvm-3.9-dev llvm-3.9-runtime libclang1-3.9.

Now to configure Mesa, start again with the build log, but for the 32-bit version of the package. Find i386 architecture on the buildd page, and open "Installed" again. Find /configure. This string however is used to build on 32-bit system proper. We need to adjust it to cross compile from 64-bit to 32-bit. The key parts here are adding -m32 to compiler invocations, and setting --build to 64-bit to trigger cross compilation. I.e. that's the most relevant part: CC="gcc -m32" CXX="g++ -m32" --build=x86_64-linux-gnu --host=i686-pc-linux-gnu That's what I came up with:

./configure CC="gcc -m32" CXX="g++ -m32" --build=x86_64-linux-gnu --host=i686-pc-linux-gnu --prefix=/opt/mesa-master --includedir=\${prefix}/include --mandir=\${prefix}/share/man --infodir=\${prefix}/share/info --sysconfdir=/etc --localstatedir=/var --disable-silent-rules --libdir=\${prefix}/x86 --libexecdir=\${prefix}/x86 --disable-maintainer-mode --disable-dependency-tracking --enable-dri "--with-dri-drivers= nouveau i965" --with-dri-driverdir=/usr/lib/i386-linux-gnu/dri --with-dri-searchpath=/usr/lib/i386-linux-gnu/dri:\\\$\${ORIGIN}/dri:/usr/lib/dri "--with-vulkan-drivers= intel radeon" --enable-osmesa --enable-glx-tls --enable-shared-glapi --enable-texture-float --disable-xvmc --disable-omx --enable-driglx-direct --enable-dri3 "--with-egl-platforms=x11 wayland drm" --enable-xa --enable-opencl --enable-opencl-icd --enable-gallium-llvm ac_cv_path_LLVM_CONFIG=llvm-config-3.9 --enable-vdpau --enable-va --enable-gallium-extra-hud --enable-lmsensors "--with-gallium-drivers= nouveau svga virgl radeonsi swrast" --enable-gles1 --enable-gles2 "CFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong -Wformat -Werror=format-security -Wall" "CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2" "CXXFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong -Wformat -Werror=format-security -Wall" "FCFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong" "FFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong" "GCJFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong" LDFLAGS=-Wl,-z,relro "OBJCFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong -Wformat -Werror=format-security" "OBJCXXFLAGS=-g -O2 -fdebug-prefix-map=/«PKGBUILDDIR»=. -fstack-protector-strong -Wformat -Werror=format-security"
make -j$(nproc)

Once succeeded, publish the result and clean up ownership:

mv -v x86/gallium/* x86/
rmdir x86/gallium

sudo mv -v x86 /opt/mesa-master/
sudo cp src/intel/vulkan/intel_icd.i686.json /opt/mesa-master/x86/
sudo cp src/amd/vulkan/radeon_icd.i686.json /opt/mesa-master/x86/
sudo chown -R root:root /opt/mesa-master

You should be ready to use it with some 32-bit applications.

OpenGL (Shadow Tactics: Blades of the Shogun, 32-bit GOG version):

LD_LIBRARY_PATH=/opt/mesa-master/x86:$LD_LIBRARY_PATH LIBGL_DRIVERS_PATH=/opt/mesa-master/x86 EGL_DRIVERS_PATH=/opt/mesa-master/x86 ./start.sh

Vulkan (Vikings Village demo 32-bit):

LD_LIBRARY_PATH=/opt/mesa-master/x86:$LD_LIBRARY_PATH VK_ICD_FILENAMES=/opt/mesa-master/x86/radeon_icd.i686_64.json ./vv.x86

You can run playonlinux like this with both custom Vulkan and OpenGL support (this will allow you running 32-bit games in Wine):

LD_LIBRARY_PATH=/opt/mesa-master/x86:$LD_LIBRARY_PATH LIBGL_DRIVERS_PATH=/opt/mesa-master/x86 EGL_DRIVERS_PATH=/opt/mesa-master/x86 VK_ICD_FILENAMES=/opt/mesa-master/x86/radeon_icd.i686_64.json playonlinux

For 64-bit ones, change accordingly.

Again, in the Vulkan examples I assume radv (AMD) usage. If you are using Intel, change VK_ICD_FILENAMES=/opt/mesa-master/x86/radeon_icd.i686.json to VK_ICD_FILENAMES=/opt/mesa-master/x86/intel_icd.i686.json.