From a4de39c10d50efbbd25c5b7403f0e6a084bf2694 Mon Sep 17 00:00:00 2001 From: Lucas Fryzek Date: Thu, 16 May 2024 15:50:00 +0100 Subject: [PATCH] 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: --- docs/android.rst | 249 ++++++++++++++++++++++++++++++++++++++ docs/drivers/llvmpipe.rst | 74 +++++++++++ 2 files changed, 323 insertions(+) diff --git a/docs/android.rst b/docs/android.rst index 207f9054aee..cc5909ee916 100644 --- a/docs/android.rst +++ b/docs/android.rst @@ -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. diff --git a/docs/drivers/llvmpipe.rst b/docs/drivers/llvmpipe.rst index db45f9f2531..b2dcdbee674 100644 --- a/docs/drivers/llvmpipe.rst +++ b/docs/drivers/llvmpipe.rst @@ -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 -----