docs/android: Add llvmpipe instructions

Add instructions for how to build llvmpipe for android as well as
documentation to build an Android image that directly includes the
out-of-tree built libraries.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29344>
This commit is contained in:
Lucas Fryzek 2024-05-16 15:50:00 +01:00 committed by Marge Bot
parent 0dce939e6d
commit a4de39c10d
2 changed files with 323 additions and 0 deletions

View File

@ -11,6 +11,10 @@ needs a built Android tree to build against, and it has never been
tested in CI. The Meson build system flow is frequently used by
Chrome OS developers for building and testing Android drivers.
When building llvmpipe or lavapipe for Android the ndk-build workflow
is also used, but there are additional steps required to add the driver
to the Android OS image.
Building using the Android NDK
------------------------------
@ -175,3 +179,248 @@ container and let it restart:
.. code-block:: sh
kill $(cat /run/containers/android-run_oci/container.pid )
Adding drivers to Android OS image
----------------------------------
When building your own Android OS images it's possible to add
drivers built out of tree directly into the OS image. For
running llvmpipe and lavapipe on Android this step is required
to ensure Android is able to load the drivers correctly.
The following steps provide and example for building
the android cuttlefish image following the official Android
documentation from https://source.android.com/docs/setup
When building llvmpipe or lavapipe for Android, it is required
to do this so that the permissions for accessing the library
are set correctly.
Following the Android documentation, we can run the following
commands
.. code-block:: sh
repo init -b main -u https://android.googlesource.com/platform/manifest
repo sync -c -j8
source build/envsetup.sh
lunch aosp_cf_x86_64_phone-trunk_staging-userdebug
Be aware that the sync command can take a long time to run as
it will download all of the source code. This will set up
the ``aosp_cf_x86_64_phone-trunk_staging-userdebug`` build target
for Android. Please note that the x86_64 cuttlefish target will require
you to build mesa for 32bit and 64bit. Next we need to copy the build
driver libraries into the source tree of Android and patch the binary names.
Note that as of ``9b7bb6cc9fa``, libgallium will include the build tag in the
name, so the name of that library will need to match the tag used in the build.
.. code-block:: sh
mkdir prebuilts/mesa
mkdir prebuilts/mesa/x86_64
mkdir prebuilts/mesa/x86
cp ${INSTALL_PREFIX_64}/lib/libEGL.so prebuilts/mesa/x86_64/
cp ${INSTALL_PREFIX_64}/lib/libglapi.so prebuilts/mesa/x86_64/
cp ${INSTALL_PREFIX_64}/lib/libgallium-24.3.0-devel.so prebuilts/mesa/x86_64/
cp ${INSTALL_PREFIX_64}/lib/libGLESv1_CM.so prebuilts/mesa/x86_64/
cp ${INSTALL_PREFIX_64}/lib/libGLESv2.so prebuilts/mesa/x86_64/
cp ${INSTALL_PREFIX_64}/lib/libvulkan_lvp.so prebuilts/mesa/x86_64/
cp ${INSTALL_PREFIX_32}/lib/libEGL.so prebuilts/mesa/x86
cp ${INSTALL_PREFIX_32}/lib/libglapi.so prebuilts/mesa/x86
cp ${INSTALL_PREFIX_32}/lib/libgallium-24.3.0-devel.so prebuilts/mesa/x86/
cp ${INSTALL_PREFIX_32}/lib/libGLESv1_CM.so prebuilts/mesa/x86
cp ${INSTALL_PREFIX_32}/lib/libGLESv2.so prebuilts/mesa/x86
cp ${INSTALL_PREFIX_32}/lib/libvulkan_lvp.so prebuilts/mesa/x86
patchelf --set-soname libEGL_lp.so prebuilts/mesa/x86_64/libEGL.so
patchelf --set-soname libGLESv1_CM_lp.so prebuilts/mesa/x86_64/libGLESv1_CM.so
patchelf --set-soname libGLESv2_lp.so prebuilts/mesa/x86_64/libGLESv2.so
patchelf --set-soname vulkan.lvp.so prebuilts/mesa/x86_64/libvulkan_lvp.so
patchelf --set-soname libEGL_lp.so prebuilts/mesa/x86/libEGL.so
patchelf --set-soname libGLESv1_CM_lp.so prebuilts/mesa/x86/libGLESv1_CM.so
patchelf --set-soname libGLESv2_lp.so prebuilts/mesa/x86/libGLESv2.so
patchelf --set-soname vulkan.lvp.so prebuilts/mesa/x86/libvulkan_lvp.so
We then need to create an ``prebuilts/mesa/Android.bp`` build file to include
the libraries in the build.
.. code-block::
cc_prebuilt_library_shared {
name: "libglapi",
arch: {
x86_64: {
srcs: ["x86_64/libglapi.so"],
},
x86: {
srcs: ["x86/libglapi.so"],
},
},
strip: {
none: true,
},
relative_install_path: "egl",
shared_libs: ["libc", "libdl", "liblog", "libm"],
vendor: true
}
cc_prebuilt_library_shared {
name: "libgallium-24.3.0-devel",
arch: {
x86_64: {
srcs: ["x86_64/libgallium-24.3.0-devel.so"],
},
x86: {
srcs: ["x86/libgallium-24.3.0-devel.so"],
},
},
strip: {
none: true,
},
relative_install_path: "egl",
shared_libs: ["libc", "libdl", "liblog", "libm"],
check_elf_files: false,
vendor: true
}
cc_prebuilt_library_shared {
name: "libEGL_lp",
arch: {
x86_64: {
srcs: ["x86_64/libEGL.so"],
},
x86: {
srcs: ["x86/libEGL.so"],
},
},
strip: {
none: true,
},
relative_install_path: "egl",
shared_libs: ["libc", "libdl", "liblog", "libm", "libcutils", "libdrm", "libhardware", "liblog", "libnativewindow", "libsync"],
check_elf_files: false,
vendor: true
}
cc_prebuilt_library_shared {
name: "libGLESv1_CM_lp",
arch: {
x86_64: {
srcs: ["x86_64/libGLESv1_CM.so"],
},
x86: {
srcs: ["x86/libGLESv1_CM.so"],
},
},
strip: {
none: true,
},
relative_install_path: "egl",
shared_libs: ["libc", "libdl", "liblog", "libm"],
check_elf_files: false,
vendor: true
}
cc_prebuilt_library_shared {
name: "libGLESv2_lp",
arch: {
x86_64: {
srcs: ["x86_64/libGLESv2.so"],
},
x86: {
srcs: ["x86_64/libGLESv2.so"],
},
},
strip: {
none: true,
},
relative_install_path: "egl",
shared_libs: ["libc", "libdl", "liblog", "libm"],
check_elf_files: false,
vendor: true
}
cc_prebuilt_library_shared {
name: "vulkan.lvp",
arch: {
x86_64: {
srcs: ["x86_64/libvulkan_lvp.so"],
},
x86: {
srcs: ["x86/libvulkan_lvp.so"],
},
},
strip: {
none: true,
},
relative_install_path: "hw",
shared_libs: ["libc", "libdl", "liblog", "libm", "libcutils", "libdrm", "liblog", "libnativewindow", "libsync", "libz"],
vendor: true
}
Next we need to update the device configuration to include the libraries
in the build, as well as set the appropriate system properties. We can
create the file
``device/google/cuttlefish/shared/mesa/device_vendor.mk``
.. code-block:: makefile
PRODUCT_SOONG_NAMESPACES += prebuilts/mesa
PRODUCT_PACKAGES += libglapi \
libGLESv1_CM_lp \
libGLESv2_lp \
libEGL_lp \
libgallium-24.3.0-devel.so \
vulkan.lvp
PRODUCT_VENDOR_PROPERTIES += \
ro.hardware.egl=lp \
ro.hardware.vulkan=lvp \
mesa.libgl.always.software=true \
mesa.android.no.kms.swrast=true \
debug.hwui.renderer=opengl \
ro.gfx.angle.supported=false \
debug.sf.disable_hwc_vds=1 \
ro.vendor.hwcomposer.mode=client
Also the file ``device/google/cuttlefish/shared/mesa/BoardConfig.mk``
.. code-block:: makefile
BOARD_VENDOR_SEPOLICY_DIRS += \
device/google/cuttlefish/shared/mesa/sepolicy
Next the file ``device/google/cuttlefish/shared/mesa/sepolicy/file_contexts``
.. code-block:: sh
/vendor/lib(64)?/egl/libEGL_lp\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/egl/libGLESv1_CM_lp\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/egl/libGLESv2_lp\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/egl/libglapi\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/egl/libgallium\-24.3.0\-devel\.so u:object_r:same_process_hal_file:s0
/vendor/lib(64)?/hw/vulkan\.lvp\.so u:object_r:same_process_hal_file:s0
After creating these files we need to modify the existing config files
to include these build files. First we modify
``device/google/cuttlefish/shared/phone/device_vendor.mk``
to add the below code in the spot where other device_vendor
files are included.
.. code-block:: sh
$(call inherit-product, device/google/cuttlefish/shared/mesa/device_vendor.mk)
Lastly we modify
``device/google/cuttlefish/vsoc_x86_64/BoardConfig.mk`` to include
the following line where the other BoardConfig files are included
.. code-block:: sh
-include device/google/cuttlefish/shared/mesa/BoardConfig.mk
Then we are set to continue following the official instructions to
build the cuttlefish target and run it in the cuttlefish emulator.

View File

@ -83,6 +83,80 @@ To build everything on Linux invoke meson as:
meson -D glx=xlib -D gallium-drivers=swrast
ninja
To build on Android requires the additional step of building LLVM
for Android using the NDK. Before following the steps in
:doc:`Android's documentation <../android>` you must build a version
of LLVM that targets the NDK with all the required libraries for
llvmpipe, and then create a wrap file so the meson knows where to
find the LLVM libraries. It can be a bit tricky to get LLVM to build
properly using the Android NDK, so the below cmake command can be
used as a reference to configure LLVM to build with the NDK for x86.
You need to set the ``ANDROID_NDK_ROOT`` and ``INSTALL_PREFIX``
environment variable appropriately.
.. code-block:: sh
cmake ../llvm-project-18.1.1.src/llvm \
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=x86_64 \
-DANDROID_PLATFORM=android-23 \
-DANDROID_NDK=${ANDROID_NDK_ROOT} \
-DCMAKE_ANDROID_ARCH_ABI=x86_64 \
-DCMAKE_ANDROID_NDK=${ANDROID_NDK_ROOT} \
-DCMAKE_BUILD_TYPE=MinSizeRel \
-DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=23 \
-DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \
-DCMAKE_CXX_FLAGS='-march=x86-64 --target=x86_64-linux-android23 -fno-rtti' \
-DLLVM_HOST_TRIPLE=x86_64-linux-android23 \
-DLLVM_TARGETS_TO_BUILD=X86 \
-DLLVM_BUILD_LLVM_DYLIB=OFF \
-DLLVM_BUILD_TESTS=OFF \
-DLLVM_BUILD_EXAMPLES=OFF \
-DLLVM_BUILD_DOCS=OFF \
-DLLVM_BUILD_TOOLS=OFF \
-DLLVM_ENABLE_RTTI=OFF \
-DLLVM_BUILD_INSTRUMENTED_COVERAGE=OFF \
-DLLVM_NATIVE_TOOL_DIR=${ANDROID_NDK_ROOT}toolchains/llvm/prebuilt/linux-x86_64/bin \
-DLLVM_ENABLE_PIC=False
make -j$(nproc) install
You will also need to create a wrap file, so that meson is able
to find the LLVM libraries built with the NDK. The process for this
is described in :doc:`meson documentation <../meson>`. For example a
file like this would work ``subprojects/llvm/meson.build`` where
``INSTALL_PREFIX`` is replaced with the path LLVM was installed to.
.. code-block::
project('llvm', ['cpp'])
cpp = meson.get_compiler('cpp')
_deps = []
_search = join_paths('$INSTALL_PREFIX', 'lib')
foreach d: ['libLLVMAggressiveInstCombine', 'libLLVMAnalysis', 'libLLVMAsmParser', 'libLLVMAsmPrinter', 'libLLVMBinaryFormat', 'libLLVMBitReader', 'libLLVMBitstreamReader', 'libLLVMBitWriter', 'libLLVMCFGuard', 'libLLVMCFIVerify', 'libLLVMCodeGen', 'libLLVMCodeGenTypes', 'libLLVMCore', 'libLLVMCoroutines', 'libLLVMCoverage', 'libLLVMDebugInfoBTF', 'libLLVMDebugInfoCodeView', 'libLLVMDebuginfod', 'libLLVMDebugInfoDWARF', 'libLLVMDebugInfoGSYM', 'libLLVMDebugInfoLogicalView', 'libLLVMDebugInfoMSF', 'libLLVMDebugInfoPDB', 'libLLVMDemangle', 'libLLVMDiff', 'libLLVMDlltoolDriver', 'libLLVMDWARFLinker', 'libLLVMDWARFLinkerClassic', 'libLLVMDWARFLinkerParallel', 'libLLVMDWP', 'libLLVMExecutionEngine', 'libLLVMExegesis', 'libLLVMExegesisX86', 'libLLVMExtensions', 'libLLVMFileCheck', 'libLLVMFrontendDriver', 'libLLVMFrontendHLSL', 'libLLVMFrontendOffloading', 'libLLVMFrontendOpenACC', 'libLLVMFrontendOpenMP', 'libLLVMFuzzerCLI', 'libLLVMFuzzMutate', 'libLLVMGlobalISel', 'libLLVMHipStdPar', 'libLLVMInstCombine', 'libLLVMInstrumentation', 'libLLVMInterfaceStub', 'libLLVMInterpreter', 'libLLVMipo', 'libLLVMIRPrinter', 'libLLVMIRReader', 'libLLVMJITLink', 'libLLVMLibDriver', 'libLLVMLineEditor', 'libLLVMLinker', 'libLLVMLTO', 'libLLVMMC', 'libLLVMMCA', 'libLLVMMCDisassembler', 'libLLVMMCJIT', 'libLLVMMCParser', 'libLLVMMIRParser', 'libLLVMObjCARCOpts', 'libLLVMObjCopy', 'libLLVMObject', 'libLLVMObjectYAML', 'libLLVMOption', 'libLLVMOrcDebugging', 'libLLVMOrcJIT', 'libLLVMOrcShared', 'libLLVMOrcTargetProcess', 'libLLVMPasses', 'libLLVMProfileData', 'libLLVMRemarks', 'libLLVMRuntimeDyld', 'libLLVMScalarOpts', 'libLLVMSelectionDAG', 'libLLVMSupport', 'libLLVMSymbolize', 'libLLVMTableGen', 'libLLVMTableGenCommon', 'libLLVMTableGenGlobalISel', 'libLLVMTarget', 'libLLVMTargetParser', 'libLLVMTextAPI', 'libLLVMTextAPIBinaryReader', 'libLLVMTransformUtils', 'libLLVMVectorize', 'libLLVMWindowsDriver', 'libLLVMWindowsManifest', 'libLLVMX86AsmParser', 'libLLVMX86CodeGen', 'libLLVMX86Desc', 'libLLVMX86Disassembler', 'libLLVMX86Info', 'libLLVMX86TargetMCA', 'libLLVMXRay']
_deps += cpp.find_library(d, dirs : _search)
endforeach
dep_llvm = declare_dependency(
include_directories : include_directories('$INSTALL_PREFIX/include'),
dependencies : _deps,
version : '6.0.0',
)
has_rtti = false
irbuilder_h = files('$INSTALL_PREFIX/include/llvm/IR/IRBuilder.h')
Afterwards you can continue following the instructors to build mesa
on :doc:`Android <../android>` and follow the steps to add the driver
directly to an Android OS image. Please note that you'll need to set
``-Ddri-search-path`` when building the driver, so that the loader
will be able to find the driver libraries in the vendor partition
``/vendor/lib(64)/egl``.
Using
-----