Skip to content

Instantly share code, notes, and snippets.

@Venemo
Last active March 14, 2023 20:33
Embed
What would you like to do?
How to build and use mesa from source

Building and using mesa for development and testing

This explains how to build mesa from source, and how to use the custom built mesa to run some apps and games, without needing to replace the mesa libraries that your operating system runs on.

Let's assume that you are using an x86_64 system.

Building mesa

Overview

Here is what we are going to do:

  • Install all build dependencies for mesa
  • Clone the mesa repo to ~/Projects/mesa
  • Build mesa
  • Install the mesa version you just built into ~/mesa (not the same as the above directory)
  • Create a script which can tell games / apps to use the libraries from ~/mesa instead of what is on your system out of the box.

Step 1. Install dependencies

Use your distro package manager to install mesa dependencies. If you're on a different distro, you will need to substitute with the correct commands for your package manager. The packages are usually named similarly but maybe have a different naming convention (eg. -dev vs. -devel, etc.).

This works on Fedora 35:

dnf install git meson ninja-build gcc gcc-c++ cmake.i686 cmake.x86_64 glibc-devel.i686 glibc-devel.x86_64 valgrind-devel.i686 valgrind-devel.x86_64 bison flex vulkan*.x86_64 vulkan*.i686 libdrm-devel.x86_64 libdrm-devel.i686 libvdpau-devel.x86_64 libvdpau-devel.i686 libva-devel.x86_64 libva-devel.i686 libomxil-bellagio-devel.x86_64 libomxil-bellagio-devel.i686 zlib-devel.x86_64 zlib-devel.i686 llvm-devel.x86_64 llvm-devel.i686 elfutils-libelf-devel.x86_64 elfutils-libelf-devel.i686 wayland*-devel.x86_64 wayland*-devel.i686 wayland-protocols-devel libX*-devel.x86_64 libX*-devel.i686 libunwind-devel.x86_64 libunwind-devel.i686 libxshmfence-devel.x86_64 libxshmfence-devel.i686 lm_sensors-devel.x86_64 lm_sensors-devel.i686 expat-devel.x86_64 expat-devel.i686 libzstd-devel.x86_64 libzstd-devel.i686 pkgconf-pkg-config.i686 pkgconf-pkg-config.x86_64 libffi-devel.i686 libffi-devel.x86_64 libxcb-devel.i686 libxcb-devel.x86_64

Step 2. Clone the mesa repo

I usually put every git repo I work with into a directory such as ~/Projects - I recommend the same to you.

mkdir -p ~/Projects
cd ~/Projects
git clone https://gitlab.freedesktop.org/mesa/mesa.git

Step 3. 64-bit build

We're assuming that your distro uses lib64 for the 64-bit libraries like Fedora. If not, adjust the meson commands below according to your distro. The compiled libraries will go into ~/mesa for the sake of simplicity.

This command will build both Intel and AMD drivers in release mode:

# Enter the mesa root directory
cd mesa
# Configure the build with meson
meson build64 --libdir lib64 --prefix $HOME/mesa -Dgallium-drivers=radeonsi,swrast,iris,zink -Dvulkan-drivers=intel,amd -Dgallium-nine=true -Dosmesa=false -Dbuildtype=release
# Compile with ninja
ninja -C build64 install

Config with AMD drivers only in release mode (recommended for AMD performance testing):

meson build64 --libdir lib64 --prefix $HOME/mesa -Dgallium-drivers=radeonsi,swrast,zink -Dvulkan-drivers=amd -Dgallium-nine=true -Dosmesa=false -Dbuildtype=release
ninja -C build64 install

Config with RADV only in debug mode (recommended for bisecting RADV crashes, etc.)

meson build64radvdebug --libdir lib64 --prefix $HOME/mesa -Dgallium-drivers= -Dvulkan-drivers=amd -Dbuild-aco-tests=true -Dbuildtype=debug
ninja -C build64radvdebug install

You can compile one with ninja -C build64radvdebug and the other with ninja -C build64 - they don't interfere with each other. Of course if you use the same install prefix they will overwrite each other when you install them.

Note about upgrading to a different version of mesa

You can use the usual git commands for updating, for example git pull etc. You don't need to re-run meson but you do need to re-run ninja (eg. ninja -C build64 install) to compile and install the changes in the new version.

Step 4. 32-bit build on an x86_64 system (skip when only testing a 64-bit game)

If you don't use Fedora (or another Red Hat family distro), replace i686-redhat-linux-gnu-pkg-config with the correct 32-bit pkg-config executable for your distro. Also verify the location of llvm-config-32 which might be different on another distro.

Make sure the meson cross directory exists:

mkdir -p ~/.local/share/meson/cross

Create a meson cross file here: ~/.local/share/meson/cross/gcc-i686 with the following content:

[binaries]
c='gcc'
cpp='g++'
ar='ar'
strip='strip'
pkgconfig='i686-redhat-linux-gnu-pkg-config'
llvm-config='/usr/bin/llvm-config-32'

[properties]
c_args=['-m32', '-march=native']
c_link_args=['-m32']
cpp_args=['-m32', '-march=native']
cpp_link_args=['-m32']

[host_machine]
system='linux'
cpu_family='x86'
cpu='x86'
endian='little'

Now you can use it to build 32-bit mesa libs.

32-bit config with Intel and AMD drivers only in release mode:

cd ~/Projects/mesa
meson build32 --cross-file gcc-i686 --libdir lib --prefix $HOME/mesa -Dgallium-drivers=radeonsi,swrast,iris,zink -Dvulkan-drivers=intel,amd -Dgallium-nine=true -Dosmesa=false -Dbuildtype=release
ninja -C build32 install

32-bit config with AMD drivers only:

meson build32 --cross-file gcc-i686 --libdir lib --prefix $HOME/mesa -Dgallium-drivers=radeonsi,swrast,zink -Dvulkan-drivers=amd -Dgallium-nine=true -Dosmesa=false -Dbuildtype=release
ninja -C build32 install

Note that you can build both the x86_64 and the i686 libraries together and they can still all go to ~/mesa, meaning there is no need to configure anything else when you need both 32 and 64-bit. You can use all of that with either 32-bit or 64-bit games.

Using the compiled mesa binaries

Running through a script (recommended for testing a single game or app)

Create a script file like this, eg. nano ~/mesa-run.sh
If you used a different install prefix or a different lib dir above, you will need to adjust this script accordingly.

#!/bin/sh

MESA=$HOME/mesa \
LD_LIBRARY_PATH=$MESA/lib64:$MESA/lib:$LD_LIBRARY_PATH \
LIBGL_DRIVERS_PATH=$MESA/lib64/dri:$MESA/lib/dri \
VK_ICD_FILENAMES=$MESA/share/vulkan/icd.d/radeon_icd.x86_64.json:$MESA/share/vulkan/icd.d/radeon_icd.x86.json \
D3D_MODULE_PATH=$MESA/lib64/d3d/d3dadapter9.so.1:$MESA/lib/d3d/d3dadapter9.so.1 \
    exec "$@"

Don't forget to add executable permissions to the script:

chmod +x ~/mesa-run.sh

Now you can run your games like:

~/mesa-run.sh vkcube

Note about games with a 32-bit launcher

Some games have a launcher which is a small app that doesn't do anything useful other than launching the game. These are usually 32-bit, so if you want to run a game that has such a launcher and it doesn't work, you may need to do the 32-bit build to make it work.

Testing a Steam game with your custom built mesa:

  1. Compile mesa as written above
  2. Create the ~/mesa-run.sh script as above
  3. First make sure it works correctly with vkcube or another simple sample app outside of Steam
  4. Open Steam, go to your Library
  5. Right-click the game, click "Properties"
  6. In the "Launch options" type:
    ~/mesa-run.sh %command%

Alternative: sourcing a script method

Use this when you want all apps you launch from a terminal to use your custom built mesa.

Create a script at ~/mesa.sh with the following content.
If you used a different install prefix or a different lib dir above, you will need to adjust this script accordingly.

#!/bin/sh

MESA=$HOME/mesa

export LD_LIBRARY_PATH=$MESA/lib64:$MESA/lib:$LD_LIBRARY_PATH
export LIBGL_DRIVERS_PATH=$MESA/lib64/dri:$MESA/lib/dri
export VK_ICD_FILENAMES=$MESA/share/vulkan/icd.d/radeon_icd.x86_64.json:$MESA/share/vulkan/icd.d/radeon_icd.i686.json
export D3D_MODULE_PATH=$MESA/lib64/d3d/d3dadapter9.so.1:$MESA/lib/d3d/d3dadapter9.so.1

Now you can just source mesa.sh and then anything launched from that terminal will use the mesa libs you just built.

For example:

source ~/mesa.sh
vkcube

To verify that it uses the version of mesa you want:

source ~/mesa.sh
vulkaninfo

Using RADV with RGP

# Run RADV with pipeline tracing enabled, and specify a trigger file
RADV_THREAD_TRACE_PIPELINE=1 RADV_THREAD_TRACE_TRIGGER=/tmp/trigger ~/mesa-run.sh ./bin/triangle

# From a different terminal, touch the trigger file. This will make RADV create an RGP capture in /tmp
touch /tmp/trigger

Building LLVM and using it with mesa (skip this unless you know you specifically need it)

Sometimes you need to test the very latest LLVM and use it without messing up your system packages.

Here are some useful cmake options:

  • CMAKE_INSTALL_PREFIX - for simplicity, let's just use the same prefix as used by your mesa build
  • LLVM_LIBDIR_SUFFIX - for distros that use /usr/lib64 or a similar convention, eg. set this to 64 on Fedora

Example:

cd llvm-project/llvm
mkdir build
cd build
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/mesa -DLLVM_LIBDIR_SUFFIX=64 -DLLVM_TARGETS_TO_BUILD="AMDGPU" -DLLVM_OPTIMIZED_TABLEGEN=ON -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON -DLLVM_INCLUDE_EXAMPLES=OFF
ninja
ninja install

After this, you need to rebuild mesa. First, tell mesa's meson to use the LLVM that you just built.

Create a meson native file at $HOME/.local/share/meson/native/my-llvm-x64 with the following content. Substitute Timur with your own username.

[binaries]
llvm-config = "/home/Timur/mesa/bin/llvm-config"

Finally, specify this to meson using the --native-file=my-llvm-x64 argument, for example:

meson build64 --libdir lib64 --prefix $HOME/mesa -Dgallium-drivers=radeonsi,swrast -Dvulkan-drivers=amd -Dgallium-nine=true -Dosmesa=false -Dbuildtype=release --native-file=my-llvm-x64
ninja -C build64 install
@OmarEmaraDev
Copy link

OmarEmaraDev commented Mar 24, 2021

It should be noted that mesa also depends on Clang for Clover and possibly other drivers, so if you build with any of those drivers, you also need to do the following:

  • LLVM needs to be built with -DLLVM_ENABLE_PROJECTS=clang , otherwise system-wide clang headers will be used.
  • Mesa needs to be configured with -Dcmake_module_path=<install directory>/lib/cmake/clang/, otherwise the driver will be linked with system-wide clang. Alternatively, define CMAKE_MODULE_PATH in the cmake section of the native meson file as follows:
    [binaries]
    llvm-config = '<install directory>/bin/llvm-config'
    
    [cmake]
    CMAKE_MODULE_PATH = '<install directory>/lib/cmake/clang/'

Also, note that the meson native file should use single quotes instead of double ones.
And I think using the extension .ini is a good idea for this file.

@Venemo
Copy link
Author

Venemo commented Mar 25, 2021

It should be noted that mesa also depends on Clang for Clover and possibly other drivers, so LLVM needs to be built with -DLLVM_ENABLE_PROJECTS=clang if you build with any of those drivers, otherwise system-wide clang will be used.

True, though I'm not building Clover usually.

Also, the meson native file should use single quotes instead of double ones.

The meson docs also use single quotes so I think that's okay.

@noobuoy
Copy link

noobuoy commented Sep 14, 2021

Thanks a lot for this tutorial. But can you tell me how to build 32 bit LLVM for 32 bit MESA?

@Venemo
Copy link
Author

Venemo commented Sep 15, 2021

Thanks a lot for this tutorial. But can you tell me how to build 32 bit LLVM for 32 bit MESA?

I never needed that, but according to their docs you need LLVM_BUILD_32_BITS

@Kzimir
Copy link

Kzimir commented Nov 5, 2021

Hello Venemo,
I build myself libdrm on Debian Stable (too old for Mesa-git) - Do you know how to tell mesa's meson to use my libdrm build ?
Thanks,

@Venemo
Copy link
Author

Venemo commented Nov 8, 2021

@Odelpasso Usually libdrm is quite stable and rarely breaks so for that, I would recommend to just build it locally and overwrite the version that was shipped in your system --- at least this hasn't caused me any trouble thus far. Let me know if works out differently for you.

@Saikatsaha1996
Copy link

Saikatsaha1996 commented Jul 11, 2022

How to build same in host mechine- aarch64
i686 cross compiler already installed..
Please guide me 🙏

Screenshot_2022-07-12-02-56-52-357_tech ula

@Venemo
Copy link
Author

Venemo commented Jul 12, 2022

@Saikatsaha1996 What exactly are you trying to do?

@Saikatsaha1996
Copy link

@Saikatsaha1996 What exactly are you trying to do?

I am trying to cross compile
In my device..

Device host - aarch64
Target - x86

How can I do it.. in my device i already installed cross build for i386 pkg

@Venemo
Copy link
Author

Venemo commented Jul 12, 2022

@Saikatsaha1996 The cross-compilation is likely going to take a long time and you can't run the cross-compiled code on your aarch64 device. I have never done this, but I think maybe you can create a meson cross file for your cross-compiler similar to what I show in "Step 4. 32-bit build on an x86_64 system" but with more options. You can look into the meson documentation to see how to write a cross file. I don't have aarch64 here, so I can't help you more, sorry.

@Saikatsaha1996
Copy link

@Saikatsaha1996 The cross-compilation is likely going to take a long time and you can't run the cross-compiled code on your aarch64 device. I have never done this, but I think maybe you can create a meson cross file for your cross-compiler similar to what I show in "Step 4. 32-bit build on an x86_64 system" but with more options. You can look into the meson documentation to see how to write a cross file. I don't have aarch64 here, so I can't help you more, sorry.

Ohhh 🥺 actually i am finding cross file x86 on aarch64 system..

@alosarjos
Copy link

Hi there!

I saw this guide, and looks like a great option for game since mesa evolves so fast. I'm just curious if there are any drawbacks for doing this (mesa-stable for the system and mesa-git for games)?

@Venemo
Copy link
Author

Venemo commented Aug 24, 2022

@alosarjos Mesa main may be unstable and may have received insuffcient testing. Sometimes things break. This question is the same as: is there a drawback for getting a cookie straight from the oven vs. buying it in the shop? Yes it's more tasty but you may burn yourself with it.

@alosarjos
Copy link

I understand that, but my question is more related to the fact having both mesa versions loaded at the same time

@Venemo
Copy link
Author

Venemo commented Aug 24, 2022

They are not loaded at the same time. Some apps load one set of libraries the others load a different set. The only risk from doing that, is when the version used by your compositor is incompatible with the version used by an application. We usually strive to keep mesa versions compatible but we don't maintain compatibility forever, so it can happen that if your system has a very old version then you may see issues such as corruption if an app loads a too new version.

@maitpate
Copy link

HI, I am trying to build mesa as you suggested. I am getting this error :
Is cross compiler: False.
Sanity check compiler command line: cc sanitycheckc.c -o sanitycheckc.exe -pthread -I/usr//include -D_FILE_OFFSET_BITS=64 -L/usr//lib -lprotobuf -lpthreads
Sanity check compile stdout:


Sanity check compile stderr:
/usr//bin/ld: cannot find -lpthreads: No such file or directory
collect2: error: ld returned 1 exit status

Any idea on this issue ? Thanks in advance

@Venemo
Copy link
Author

Venemo commented Dec 23, 2022

@maitpate It's unclear which command gives you this error, and you also forgot to mention what system you are using. I can't help you without knowing those things.

@maitpate
Copy link

I am using this cmd in created build directory : "meson .." . I am running on linux.

@Venemo
Copy link
Author

Venemo commented Dec 23, 2022

I am using this cmd in created build directory : "meson .." .

Please follow the above instructions exactly. I never used this command.

I am running on linux.

Which Linux distro do you use?

@maitpate
Copy link

I found it in README.rst : https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/README.rst . It has been given under Build and Install section :
$ mkdir build
$ cd build
$ meson ..
$ sudo ninja install

using Ubuntu 22.04.1 LTS

@Venemo
Copy link
Author

Venemo commented Dec 23, 2022

I don't use Ubuntu so I can't help with that. Have you made sure that all dependencies are installed? If yes, then I recommend asking this question on a Ubuntu forum.

@maitpate
Copy link

sure. Thanks for the response !

@alosarjos
Copy link

I see the dri-drivers flag now shows an error saying it's not valid. Just removed it for now, but maybe wanna update the gist? I find this really useful to be honest

@Venemo
Copy link
Author

Venemo commented Feb 14, 2023

@alosarjos Thanks, yes I removed dri-drivers now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment