Stéphane Cerveau
May 15, 2020
Reading time:
Note: In September 2021, the GStreamer project merged all its git repositories into a single, unified repository, often called monorepo
. The build system referred in this post as "gst-build" is now in the root of this combined/mono repository.
gst-build is one of the main build systems used by the community to develop the GStreamer platform. In my last blog post, I presented gst-build and explained how to get started with it. Now, let's get straight to the point regarding cross-compilation.
For this example, we will target an AArch64 CPU for a Xilinx reference board, the Zynq UltraScale+ MPSoC ZCU106 Evaluation Kit. As you'll see, cross compiling can be very useful when you want to save time when working with GStreamer, or when you want to be able to work on both the host and target with the same base code.
First we'll need here to have a proper toolchain to cross-build. In my case I used the regular toolchain provided by Ubuntu installing the packages:
$ sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev-arm64-cross
This is installing a minimal toolchain in /usr/aarch64-linux-gnu/
Below the cross file used to build for aarch64, this file has been generated with this helper script allowing to generated the cross file for other target as well. As you can see, here, we don't use a dedicated rootfs because gst-build will build all that we need for the GStreamer essentials (including libffi, glib etc.).
$ ./generate-cross-file.py
[host_machine] system = 'linux' cpu_family = 'aarch64' cpu = 'arm64' endian = 'little' [properties] c_args = [] cpp_args = [] objc_args = [] objcpp_args = [] c_link_args = [] cpp_link_args = [] objc_link_args = [] objcpp_link_args = [] pkg_config_libdir = ['__unknown_sysroot__'] [binaries] c = ['aarch64-linux-gnu-gcc'] cpp = ['aarch64-linux-gnu-g++'] ar = ['aarch64-linux-gnu-ar'] pkgconfig = 'pkg-config' strip = ['aarch64-linux-gnu-strip']
Here Meson will use aarch64-linux-gnu-gxx to compile with the given arguments setup above. As Meson does not recommend to use environment variables, the cross file contains hard-coded path to the sysroot to provide package config. Indeed since Meson > 0.54, you can define pkg_config_libdir
which will help pkg-config to search for the package configuration files for the given target. You can also tell the path to the pkg-config wrapper by modifying the pkgconfig variables as well. Predefined cross file can also be found in gst-build/data/cross-files
When the cross file ready, we can now configure gst-build in order to have a dedicated build for our platform. Here I'm disabling some unnecessary options of gst-build such as libav, vaapi or gtk_doc.
⚠ Note: Make sure that you are running Meson 0.54.1 which has the necessary patch for complete support of cross-compilation, otherwise gst-build will take glib from the system (pkg_config_libdir prerequisite).
Notice that on this platform, we use gst-omx, so we also give some options specific to this platform, in particular the path to the Xilinx OpenMAX headers .
$ /path/to/meson_0_54 build-cross-arm64 --cross-file=my-meson-cross-file.txt -D omx=enabled -D sharp=disabled -D gst-omx:header_path=/opt/allegro-vcu-omx-il/omx_header -D gst-omx:target=zynqultrascaleplus -D libav=disabled -D rtsp_server=disabled -D vaapi=disabled -D disable_gst_omx=false -Dugly=disabled -Dgtk_doc=disabled -Dglib:libmount=disabled -Dintrospection=disabled
After this step, you should be able to build with ninja.
$ ninja -C build-cross-arm64
Last but not the least, you need to install the artifacts in a folder to deploy on the device, for example, by mounting it on your target with NFS. You have to provide a DESTDIR variable to ninja and it will install in $DESTDIR/usr/local/
as install prefix.
$ DESTDIR=/opt/gst-build-cross-artifacts/linux_arm64 ninja -C build-cross-arm64 install
After mounting the folder or copying it to your target, you have to set up a few variables to be able to run GStreamer pipelines:
PATH=$DESTDIR/usr/local/bin:$PATH LD_LIBRARY_PATH=$DESTDIR/usr/local/lib:$LD_LIBRARY_PATH GST_PLUGIN_PATH=$DESTDIR/usr/local/lib/gstreamer-1.0 GST_OMX_CONFIG_DIR=$DESTDIR/usr/local/etc/xdg
A python script as shell script is also available to setup the correct environment variables for your target.
$ /path_to/cross-gst-uninstalled.py /opt/gst-build-cross-artifacts/linux_arm64
To build a plugin such as wavpack which depends on the 3rd party wavpack library. You'll need to get a proper sysroot with this new library and its dependencies (if needed).
Regarding a root file-system with wavpack, I generated one with cerbero where cross compiling could be described in a next blog post :) But you should normally have it as part of your sysroot.
$ cd /opt $ git clone https://gitlab.freedesktop.org/gstreamer/cerbero $ cd cerbero $ ./cerbero-uninstalled -c config/cross-lin-arm64.cbc bootstrap $ ./cerbero-uninstalled -c config/cross-lin-arm64.cbc build wavpack
This should have generated a minimal root file-system in /opt/cerbero/build/dist/linux_arm64
which can used then with gst-build as a base root file-system.
You can now generate a new cross file with the given root file-system as parameter.
$ ./generate-cross-file.py --sysroot /opt/cerbero/build/dist/linux_arm64/ --no-include-sysroot
Here I define a sysroot to be be used but I'm disabling the use of sys_root
in the cross file to avoid Meson to tell pkg-config to prefix every path with this value. cerbero is generating pkg-config files with the sysroot path already in each pc files.
[host_machine] system = 'linux' cpu_family = 'aarch64' cpu = 'arm64' endian = 'little' [properties] c_args = [] cpp_args = [] objc_args = [] objcpp_args = [] c_link_args = ['-L/opt/cerbero/build/dist/linux_arm64', '-Wl,-rpath-link=/opt/cerbero/build/dist/linux_arm64'] cpp_link_args = ['-L/opt/cerbero/build/dist/linux_arm64', '-Wl,-rpath-link=/opt/cerbero/build/dist/linux_arm64'] objc_link_args = ['-L/opt/cerbero/build/dist/linux_arm64', '-Wl,-rpath-link=/opt/cerbero/build/dist/linux_arm64'] objcpp_link_args = ['-L/opt/cerbero/build/dist/linux_arm64', '-Wl,-rpath-link=/opt/cerbero/build/dist/linux_arm64'] pkg_config_libdir = ['/opt/cerbero/build/dist/linux_arm64/pkgconfig:/opt/NFS/cerbero_rootfs/linux_arm64//usr/share/pkgconfig'] [binaries] c = ['aarch64-linux-gnu-gcc'] cpp = ['aarch64-linux-gnu-g++'] ar = ['aarch64-linux-gnu-ar'] pkgconfig = 'pkg-config' strip = ['aarch64-linux-gnu-strip']
Now you should be able to go back to the configure/build/install step and get the wavpack in your plugins registry.
I hope you'll enjoy the use of gst-build, which is for me a very powerful and flexible tool. A lot of options can be found in the gst-build README such as the update or the use of GStreamer branches.
If you would like to learn more about gst-build or any other parts of GStreamer, please contact us!
08/10/2024
Having multiple developers work on pre-merge testing distributes the process and ensures that every contribution is rigorously tested before…
15/08/2024
After rigorous debugging, a new unit testing framework was added to the backend compiler for NVK. This is a walkthrough of the steps taken…
01/08/2024
We're reflecting on the steps taken as we continually seek to improve Linux kernel integration. This will include more detail about the…
27/06/2024
With each board running a mainline-first Linux software stack and tested in a CI loop with the LAVA test framework, the Farm showcased Collabora's…
26/06/2024
WirePlumber 0.5 arrived recently with many new and essential features including the Smart Filter Policy, enabling audio filters to automatically…
12/06/2024
Part 3 of the cmtp-responder series with a focus on USB gadgets explores several new elements including a unified build environment with…
Comments (10)
Stephane:
Sep 20, 2021 at 01:19 PM
Depending on the host and the target, the libc might be incompatible for glib and gstreamer, so better to provide a sys root according to your target or find the right combination if you install the compiler with a given package manager.
Reply to this comment
Reply to this comment
Howard Harvey:
Oct 25, 2022 at 07:13 PM
I am attempting to re-create your little Xilinx cross compile for zcu106, and have encountered a rather odd
build error:
Library dl found: YES
Checking for function "dladdr" with dependency -ldl: YES
Run-time dependency glib-2.0 found: NO (tried pkgconfig and cmake)
Looking for a fallback subproject for the dependency glib-2.0
meson.build:482:0: ERROR: Neither a subproject directory nor a glib.wrap file was found.
Exceptionally puzzling, since this is on a machine where the native x64 build comes together just fine....
Was wondering if this is something you had encountered.....
Reply to this comment
Reply to this comment
Xavier Claessens:
Oct 25, 2022 at 07:32 PM
You need to cross compile glib too, Meson is not going to use the one from your system. You should have the file gst-build/subprojects/glib.wrap to tell Meson how to cross compile GLib, are you missing that file?
Reply to this comment
Reply to this comment
Howard Harvey:
Oct 25, 2022 at 07:48 PM
Well, I'm not actually 'missing' glib.wrap...... It is in gst-build/subprojects/glib.wrap, but I suspect that I
need to install/copy it somewhere so that the meson build process cane use it? However, I did
find that if I copy it via
cp ./subprojects/glib.wrap ./subprojects/glib/subprojects
that the build gets past the glib build process
Many thanks!
Reply to this comment
Reply to this comment
Xavier Claessens:
Oct 25, 2022 at 07:59 PM
subprojects/glib.wrap should be the correct location, I'm not sure what you're doing... You could try with a more recent Meson and with GStreamer >= 1.18, gst-build is old and not used any more.
Reply to this comment
Reply to this comment
Howard Harvey:
Oct 26, 2022 at 09:23 PM
Quite right you are. Once I moved to latest-and-greatest of gstreamer, rather than the explicit 1.18 branch build, things got a whole heck of a lot easier. Many thanks for having a look at my problem and the resultant guidance.
Reply to this comment
Reply to this comment
Murari G:
Mar 19, 2024 at 10:59 AM
I am facing an issue with the cross compilation of custom gstreamer plugin to run ZCU104. How to cross compilation to run on ZCU104 board with meson build.
Reply to this comment
Reply to this comment
Olivier Crête:
Mar 19, 2024 at 12:54 PM
I'd need more details than that to be able to help you. You should post at https://discourse.gstreamer.org/ with details of what you're trying and the errors you're getting.
Reply to this comment
Reply to this comment
Murari G:
Mar 20, 2024 at 05:10 AM
I am unable to find aarch-xilinux-linux-g++ compiler binary to include the file path in the Cross file. The common image sdk of ZCU104 doesn't contain the binaries.
Reply to this comment
Reply to this comment
Olivier Crête:
Apr 19, 2024 at 05:23 PM
For any questions specific to cross-compiling with PetaLinux, your best bet is to ask on the Xilinx forums.
Reply to this comment
Reply to this comment
Add a Comment