diff options
author | Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> | 2024-05-10 20:44:54 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-05-10 20:44:54 +0000 |
commit | 012c78534f682e91f176ce8d3bd981e870c4d182 (patch) | |
tree | b4864628f94ebac688f19bd978d8961b0461b04a | |
parent | de56b2e13d31b6c065c79040d2f7b31659bcdb9e (diff) | |
parent | 8198f34df2cdbe3690c3f4d9e223ad1d925f3e96 (diff) | |
download | qemu-012c78534f682e91f176ce8d3bd981e870c4d182.tar.gz |
Merge changes from topic "qt6-linux-aarch64" into emu-master-dev
* changes:
[Qt6] Add linux-aarch64 Dockerfile to build Qt6.
[Qt6] Add linux-aarch64 native build.
-rw-r--r-- | android/build/docker/darwin-aarch64/qt6-linux-aarch64/Dockerfile | 83 | ||||
-rw-r--r-- | android/build/python/aemu/prebuilts/qt.py | 135 |
2 files changed, 171 insertions, 47 deletions
diff --git a/android/build/docker/darwin-aarch64/qt6-linux-aarch64/Dockerfile b/android/build/docker/darwin-aarch64/qt6-linux-aarch64/Dockerfile new file mode 100644 index 0000000000..887483a82c --- /dev/null +++ b/android/build/docker/darwin-aarch64/qt6-linux-aarch64/Dockerfile @@ -0,0 +1,83 @@ +# Copyright (C) 2024 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This docker image is for build Qt 6.5.3 for linux-aarch64 on an arm mac. +# We want to build on arm mac so we can use an arm linux image. +# +# To build the docker image for arm architecture: +# > docker build -t <image_name> . +# > docker run --mount type=bind,source="/Volumes/android/emu-prebuilts",target="/emu" -dt <image_name> +# > docker exec -it <container_id> bash +# $ cd emu && tools/buildSrc/servers/build_tools.py --out_dir /emu/out-prebuilts --dist_dir /emu/dist-prebuilts/12345678 --build-id 12345678 --prebuilts +FROM ubuntu:focal-20200423 + +# tzdata complains when running apt-get install below, so we need to set the timezone. +ENV TZ=America/Los_Angeles +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN apt update +# Install necessary utilities +RUN apt install -y software-properties-common curl git + +# Install python 3.10, ninja +RUN add-apt-repository -y ppa:deadsnakes/ppa +RUN apt install -y python3.10 python3.10-distutils pip ninja-build + +# Install deps for building Qt +RUN apt -y install \ + patchelf \ + libfontconfig1-dev \ + libfreetype6-dev \ + libx11-dev \ + libx11-xcb-dev \ + libxext-dev \ + libxfixes-dev \ + libxi-dev \ + libxrender-dev \ + libxcb-cursor-dev \ + libxcb-glx0-dev \ + libxcb-keysyms1-dev \ + libxcb-image0-dev \ + libxcb-shm0-dev \ + libxcb-icccm4-dev \ + libxcb-sync-dev \ + libxcb-xfixes0-dev \ + libxcb-shape0-dev \ + libxcb-randr0-dev \ + libxcb-render-util0-dev \ + libxcb-util-dev \ + libxcb-xinerama0-dev \ + libxcb-xkb-dev \ + libxkbcommon-dev \ + libxkbcommon-x11-dev \ + libsm-dev \ + libice-dev \ + libdbus-1-dev \ + libxcomposite-dev \ + libxcursor-dev \ + libxrandr-dev \ + libxshmfence-dev \ + libcupsfilters-dev \ + libegl1-mesa-dev \ + libglib2.0-dev \ + libcups2-dev \ + libnss3-dev \ + libxtst-dev \ + libxkbfile-dev \ + libdrm-dev + +# Install cmake >= 3.19; apt version is 3.16 +RUN curl -L https://github.com/Kitware/CMake/releases/download/v3.29.3/cmake-3.29.3-linux-aarch64.tar.gz > /cmake-3.29.3-linux-aarch64.tar.gz +RUN tar -xvf /cmake-3.29.3-linux-aarch64.tar.gz +ENV PATH=/cmake-3.29.3-linux-aarch64/bin:$PATH diff --git a/android/build/python/aemu/prebuilts/qt.py b/android/build/python/aemu/prebuilts/qt.py index 4b098b520f..e0d2732a16 100644 --- a/android/build/python/aemu/prebuilts/qt.py +++ b/android/build/python/aemu/prebuilts/qt.py @@ -32,6 +32,7 @@ import platform AOSP_ROOT = Path(__file__).resolve().parents[7] HOST_OS = platform.system().lower() +HOST_ARCH = platform.machine().lower() QT_VERSION = "6.5.3" QT_SUBMODULES = [ @@ -81,22 +82,25 @@ def checkDependencies(): logging.info(">> Checking Ninja >= 1.7.2") deps_common.checkNinjaVersion(min_vers=(1, 7, 2)) - # Need node.js version 12 or later for QtWebEngine - logging.info(">> Checking for node.js version >= 12") - deps_common.checkNodeJsVersion(min_vers=(12, 0)) - - # QtWebEngine needs python html5lib package - logging.info(">> Checking for python package html5lib") - deps_common.checkPythonPackage("html5lib") - - # QtWebEngine requires GNUWin32 dependencies gperf, bison, flex - # TODO(joshuaduong): Locally I installed bison from https://gnuwin32.sourceforge.net/packages.html, but maybe we use chocolatey on the buildbot. - logging.info(">> Checking for gperf") - deps_common.checkGperfVersion() - logging.info(">> Checking for bison") - deps_common.checkBisonVersion() - logging.info(">> Checking for flex") - deps_common.checkFlexVersion() + if HOST_OS == "linux" and HOST_ARCH == "aarch64": + logging.info("Skipping QtWebEngine dependency check for linux-aarch64") + else: + # Need node.js version 12 or later for QtWebEngine + logging.info(">> Checking for node.js version >= 12") + deps_common.checkNodeJsVersion(min_vers=(12, 0)) + + # QtWebEngine needs python html5lib package + logging.info(">> Checking for python package html5lib") + deps_common.checkPythonPackage("html5lib") + + # QtWebEngine requires GNUWin32 dependencies gperf, bison, flex + # TODO(joshuaduong): Locally I installed bison from https://gnuwin32.sourceforge.net/packages.html, but maybe we use chocolatey on the buildbot. + logging.info(">> Checking for gperf") + deps_common.checkGperfVersion() + logging.info(">> Checking for bison") + deps_common.checkBisonVersion() + logging.info(">> Checking for flex") + deps_common.checkFlexVersion() if HOST_OS == "windows": # - Visual Studio 2019 v16.11+ @@ -109,7 +113,7 @@ def checkDependencies(): elif HOST_OS == "darwin": # MacOS sdk >= 13 deps_mac.checkMacOsSDKVersion(min_vers=(12, 0)) - elif HOST_OS == "linux": + elif HOST_OS == "linux" and HOST_ARCH != "aarch64": pkgconfig_libs = [ ("xrender", [0, 9, 0]), ("xcb-render", [1, 11]), @@ -240,25 +244,29 @@ def configureQtBuild(srcdir, builddir, installdir, qtsubmodules, crosscompile_ta if HOST_OS == "windows": conf_args += ["-platform", "win32-msvc"] elif HOST_OS == "linux": - if crosscompile_target == "linux_aarch64": + if HOST_ARCH == "aarch64" or crosscompile_target == "linux_aarch64": # Cross-compiling requires a host installation of Qt, so we must build Qt for # linux-x86_64 prior to cross-compiling to linux_aarch64. - if not qt_host_path: - logging.fatal(f"No Qt host path was provided for {crosscompile_target} cross-compilation.") - conf_args += ["-platform", "linux-aarch64-gnu-g++", + conf_args += ["-platform", "linux-aarch64-gnu-g++"] + if crosscompile_target: + if not qt_host_path: + logging.fatal(f"No Qt host path was provided for {crosscompile_target} cross-compilation.") + # We have to disable a lot of things for cross-compilation without a full sysroot. + logging.warning("GUI support is not supported in cross-compilation.") + conf_args += [ "-device-option", "CROSS_COMPILE=aarch64-linux-gnu-", "-no-glib", "-qt-host-path", qt_host_path, "-qt-pcre", "-qt-zlib", "-qt-doubleconversion", "-qt-freetype", "-qt-harfbuzz", "-no-feature-gssapi", "-no-feature-brotli", "-no-xcb", "-no-xkbcommon", "-qt-webp", "-no-libudev", "-no-mtdev", "-no-linuxfb"] - os.environ["CC"] = "aarch64-linux-gnu-gcc" - os.environ["CXX"] = "aarch64-linux-gnu-g++" + conf_args += ["--", "-DCMAKE_SYSTEM_NAME=Linux", "-DCMAKE_SYSTEM_PROCESSOR=arm", + f"-DQT_HOST_PATH={qt_host_path}", "-DCMAKE_LINKER_FLAGS=-Wl,--as-needed"] + os.environ["CC"] = "aarch64-linux-gnu-gcc" + os.environ["CXX"] = "aarch64-linux-gnu-g++" extra_cflags = "-march=armv8-a" extra_cxxflags = "-march=armv8-a" os.environ["CFLAGS"] = extra_cflags os.environ["CXXFLAGS"] = extra_cxxflags - conf_args += ["--", "-DCMAKE_SYSTEM_NAME=Linux", "-DCMAKE_SYSTEM_PROCESSOR=arm", - f"-DQT_HOST_PATH={qt_host_path}", "-DCMAKE_LINKER_FLAGS=-Wl,--as-needed"] else: conf_args += ["-linker", "lld", "-platform", "linux-clang-libc++", @@ -281,7 +289,11 @@ def configureQtBuild(srcdir, builddir, installdir, qtsubmodules, crosscompile_ta toolchain_dir = Path(builddir) / "toolchain" os.makedirs(Path(builddir) / "toolchain") - clang_dir = deps_common.getClangDirectory() + if HOST_ARCH == "aarch64": + clang_dir = "/usr" + else: + clang_dir = deps_common.getClangDirectory() + with open(toolchain_dir / "clang", 'x') as f: f.write(f"#!/bin/sh\n{clang_dir}/bin/clang {extra_cflags} $@") os.chmod(toolchain_dir / "clang", 0o777) @@ -298,8 +310,6 @@ def configureQtBuild(srcdir, builddir, installdir, qtsubmodules, crosscompile_ta f.write(f"#!/bin/sh\n{clang_dir}/bin/lld $@") os.chmod(toolchain_dir / "lld", 0o777) - # Add path to libc++.so.1 as some binaries (syncqt) that require it are ran during the - # configure step. os.environ["LD_LIBRARY_PATH"] = str(deps_common.getClangDirectory() / "lib") addToSearchPath(str(toolchain_dir)) @@ -421,15 +431,19 @@ def mac_postInstall(installdir): def linux_postInstall(installdir, target, is_webengine): # Install prebuilt clang's libc++.so.1 and libc++abi.so.1 to lib/ as Qt's compiler # tools (moc, rcc, uic) depends on it. - clang_libs = ["libc++.so.1", "libc++abi.so.1"] - for lib in clang_libs: - src_lib = deps_common.getClangDirectory() / "lib" / lib - dst_lib = f"{installdir}/lib/{lib}" - logging.info(f"Copy {src_lib} ==> {dst_lib}") - shutil.copyfile(src_lib, dst_lib) + if HOST_ARCH == "aarch64": + sysroot_dir = Path("/lib/aarch64-linux-gnu") + else: + clang_libs = ["libc++.so.1", "libc++abi.so.1"] + clang_dir = deps_common.getClangDirectory() + sysroot_dir = Path("/lib/x86_64-linux-gnu") + for lib in clang_libs: + src_lib = clang_dir / "lib" / lib + dst_lib = f"{installdir}/lib/{lib}" + logging.info(f"Copy {src_lib} ==> {dst_lib}") + shutil.copyfile(src_lib, dst_lib) # We also need additional libraries from the sysroot for linux - sysroot_dir = Path("/lib/x86_64-linux-gnu") sysroot_libs = [ "libpcre2-16.so.0", "libfreetype.so.6", @@ -454,13 +468,33 @@ def linux_postInstall(installdir, target, is_webengine): "libfontconfig.so.1"] if target == "linux" and is_webengine: sysroot_libs += ["libjpeg.so.8"] + if target == "linux" and HOST_ARCH == "aarch64": + # Need additional libraries to build emulator + sysroot_libs += [ + "libxcb.so.1", + "libX11.so.6", + "libz.so.1", + "libpng16.so.16", + "libexpat.so.1", + "libuuid.so.1", + "libdbus-1.so.3", + "libsystemd.so.0", + "liblzma.so.5", + "liblz4.so.1", + "libgcrypt.so.20", + "libgpg-error.so.0", + "libbsd.so.0"] for lib in sysroot_libs: src_lib = sysroot_dir / lib dst_lib = f"{installdir}/lib/{lib}" logging.info(f"Copy {src_lib} ==> {dst_lib}") shutil.copyfile(src_lib, dst_lib) + if target == "linux" and HOST_ARCH == "aarch64": + # These symlinks are needed to make emulator build compile + os.symlink("libX11.so.6", f"{installdir}/lib/libX11.so") + os.symlink("libXau.so.6", f"{installdir}/lib/libXau.so") - if target != "linux_aarch64": + if target != "linux_aarch64" and HOST_ARCH != "aarch64": # need libunwind.so.1 for syncqt src_libunwind = AOSP_ROOT / "prebuilts" / "android-emulator-build" / "common" / "libunwind" \ / "linux-x86_64" / "lib" / "libunwind.so" @@ -503,10 +537,14 @@ def buildPrebuilt(args, prebuilts_out_dir): logging.fatal(f"[{vcvarsall}] does not exist") exit(-1) deps_win.inheritSubprocessEnv([vcvarsall, "amd64", ">NUL", "2>&1"]) - # Use cmake from our prebuilts - addToSearchPath(CMAKE_PATH) - # Use ninja from our prebuilts - addToSearchPath(NINJA_PATH) + + if HOST_OS == "linux" and HOST_ARCH != "aarch64": + # Use cmake from our prebuilts + addToSearchPath(CMAKE_PATH) + # Use ninja from our prebuilts + addToSearchPath(NINJA_PATH) + else: + logging.info("Using installed cmake/ninja on linux-aarch64 host") logging.info(os.environ) if not checkDependencies(): @@ -549,16 +587,19 @@ def buildPrebuilt(args, prebuilts_out_dir): postInstall(qt_install_dir, args.target, False) shutil.rmtree(qt_build_path) - logging.info("Building Qt6 w/ QtWebEngine") - qt_install_dir = os.path.join(prebuilts_out_dir, "qt") - configureQtBuild(qt_src_path, qt_build_path, qt_install_dir, QT_SUBMODULES) - buildQt(QT_SUBMODULES, qt_build_path) - installQt(QT_SUBMODULES, qt_build_path, qt_install_dir) - postInstall(qt_install_dir, args.target, True) + if HOST_OS == "linux" and HOST_ARCH == "aarch64": + logging.info("Skipping QtWebEngine build on linux-aarch64 machine") + else: + logging.info("Building Qt6 w/ QtWebEngine") + qt_install_dir = os.path.join(prebuilts_out_dir, "qt") + configureQtBuild(qt_src_path, qt_build_path, qt_install_dir, QT_SUBMODULES) + buildQt(QT_SUBMODULES, qt_build_path) + installQt(QT_SUBMODULES, qt_build_path, qt_install_dir) + postInstall(qt_install_dir, args.target, True) # Since linux_aarch64 cross-compilation requires having a host build of Qt, let's just build it # in the linux x86_64 host instead of creating an additional linux_aarch64 build target. - if HOST_OS == "linux": + if HOST_OS == "linux" and HOST_ARCH != "aarch64": logging.info("Cross-compiling Qt 6 (no QtWebEngine) for linux_aarch64") crosscompile_target = "linux_aarch64" qt_install_dir = os.path.join(prebuilts_out_dir, "qt-nowebengine-linux_aarch64") |