From 3c8016b302c658d20ebf8eebd5f32daf818a0531 Mon Sep 17 00:00:00 2001 From: kuqin12 <42554914+kuqin12@users.noreply.github.com> Date: Tue, 25 Apr 2023 15:48:19 -0700 Subject: [PATCH] BaseTools: Support custom library build for base tools on Linux ARM This change added the build script to cross compile the base tool binaries for Linux ARM/AARCH64 systems. The needed libuuid system library is pulled from source file and rebuilt to support the corresponding library dependencies. Individual tools' makefiles are also updated to link the cross compiled library as well. The EDK2 base tool build script was also updated to support such change. This was tested functional on Linux ARM host system. Cc: Rebecca Cran Cc: Liming Gao Cc: Bob Feng Cc: Yuwei Chen Signed-off-by: Kun Qin --- BaseTools/Edk2ToolsBuild.py | 93 +++++++++++++++++++- BaseTools/Source/C/DevicePath/GNUmakefile | 4 + BaseTools/Source/C/GenFv/GNUmakefile | 11 ++- BaseTools/Source/C/GenFv/GenFvInternalLib.c | 9 ++ BaseTools/Source/C/GenFw/GNUmakefile | 4 + BaseTools/Source/C/GenSec/GNUmakefile | 4 + BaseTools/Source/C/Makefiles/header.makefile | 10 +-- 7 files changed, 127 insertions(+), 8 deletions(-) diff --git a/BaseTools/Edk2ToolsBuild.py b/BaseTools/Edk2ToolsBuild.py index d511b1a2a342..9ed5367d2db8 100644 --- a/BaseTools/Edk2ToolsBuild.py +++ b/BaseTools/Edk2ToolsBuild.py @@ -43,8 +43,16 @@ def GetWorkspaceRoot(self): def GetActiveScopes(self): ''' return tuple containing scopes that should be active for this process ''' - # for now don't use scopes - return ('global',) + # Adding scope for cross compilers when building for ARM/AARCH64 + scopes = ('global',) + if GetHostInfo().os == "Linux" and self.tool_chain_tag.lower().startswith("gcc"): + if self.target_arch is None: + return scopes + if "AARCH64" in self.target_arch: + scopes += ("gcc_aarch64_linux",) + if "ARM" in self.target_arch: + scopes += ("gcc_arm_linux",) + return scopes def GetLoggingLevel(self, loggerType): ''' Get the logging level for a given type (return Logging.Level) @@ -247,6 +255,87 @@ def Go(self): return ret elif self.tool_chain_tag.lower().startswith("gcc"): + # Note: This HOST_ARCH is in respect to the BUILT base tools, not the host arch where + # this script is BUILDING the base tools. + HostInfo = GetHostInfo() + prefix = None + TargetInfoArch = None + if self.target_arch is not None: + shell_env.set_shell_var('HOST_ARCH', self.target_arch) + + if "AARCH64" in self.target_arch: + prefix = shell_env.get_shell_var("GCC5_AARCH64_PREFIX") + if prefix == None: + # now check for install dir. If set then set the Prefix + install_path = shell_environment.GetEnvironment().get_shell_var("GCC5_AARCH64_INSTALL") + + # make GCC5_AARCH64_PREFIX to align with tools_def.txt + prefix = os.path.join(install_path, "bin", "aarch64-none-linux-gnu-") + + shell_environment.GetEnvironment().set_shell_var("GCC_PREFIX", prefix) + TargetInfoArch = "ARM" + + elif "ARM" in self.target_arch: + prefix = shell_env.get_shell_var("GCC5_ARM_PREFIX") + if prefix == None: + # now check for install dir. If set then set the Prefix + install_path = shell_environment.GetEnvironment().get_shell_var("GCC5_ARM_INSTALL") + + # make GCC5_ARM_PREFIX to align with tools_def.txt + prefix = os.path.join(install_path, "bin", "arm-none-linux-gnueabihf-") + + shell_environment.GetEnvironment().set_shell_var("GCC_PREFIX", prefix) + TargetInfoArch = "ARM" + + else: + TargetInfoArch = "x86" + else: + self.target_arch = HostInfo.arch + TargetInfoArch = HostInfo.arch + # Otherwise, the built binary arch will be consistent with the host system + + # Added logic to support cross compilation scenarios + if TargetInfoArch != HostInfo.arch: + # this is defaulting to the version that comes with Ubuntu 20.04 + ver = shell_environment.GetBuildVars().GetValue("LIBUUID_VERSION", "2.34") + work_dir = os.path.join(shell_env.get_shell_var("EDK_TOOLS_PATH"), self.GetLoggingFolderRelativeToRoot()) + pack_name = f"util-linux-{ver}" + unzip_dir = os.path.join(work_dir, pack_name) + + if os.path.isfile(os.path.join(work_dir, f"{pack_name}.tar.gz")): + os.remove(os.path.join(work_dir, f"{pack_name}.tar.gz")) + if os.path.isdir(unzip_dir): + shutil.rmtree(unzip_dir) + + # cross compiling, need to rebuild libuuid for the target + ret = RunCmd("wget", f"https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/v{ver}/{pack_name}.tar.gz", workingdir=work_dir) + if ret != 0: + raise Exception(f"Failed to download libuuid version {ver} - {ret}") + + ret = RunCmd("tar", f"xvzf {pack_name}.tar.gz", workingdir=work_dir) + if ret != 0: + raise Exception(f"Failed to untar the downloaded file {ret}") + + # configure the source to use the cross compiler + pack_name = f"util-linux-{ver}" + if "AARCH64" in self.target_arch: + ret = RunCmd("sh", f"./configure --host=aarch64-linux -disable-all-programs --enable-libuuid CC={prefix}gcc", workingdir=unzip_dir) + elif "ARM" in self.target_arch: + ret = RunCmd("sh", f"./configure --host=arm-linux -disable-all-programs --enable-libuuid CC={prefix}gcc", workingdir=unzip_dir) + if ret != 0: + raise Exception(f"Failed to configure the util-linux to build with our gcc {ret}") + + ret = RunCmd("make", "", workingdir=unzip_dir) + if ret != 0: + raise Exception(f"Failed to build the libuuid with our gcc {ret}") + + shell_environment.GetEnvironment().set_shell_var("CROSS_LIB_UUID", unzip_dir) + shell_environment.GetEnvironment().set_shell_var("CROSS_LIB_UUID_INC", os.path.join(unzip_dir, "libuuid", "src")) + + ret = RunCmd("make", "clean", workingdir=shell_env.get_shell_var("EDK_TOOLS_PATH")) + if ret != 0: + raise Exception("Failed to build.") + cpu_count = self.GetCpuThreads() output_stream = edk2_logging.create_output_stream() diff --git a/BaseTools/Source/C/DevicePath/GNUmakefile b/BaseTools/Source/C/DevicePath/GNUmakefile index f61b1b2f171d..26ae14c468b7 100644 --- a/BaseTools/Source/C/DevicePath/GNUmakefile +++ b/BaseTools/Source/C/DevicePath/GNUmakefile @@ -30,6 +30,10 @@ ifeq ($(CYGWIN), CYGWIN) endif ifeq ($(LINUX), Linux) +ifndef CROSS_LIB_UUID LIBS += -luuid +else + LIBS += -L$(CROSS_LIB_UUID) +endif endif diff --git a/BaseTools/Source/C/GenFv/GNUmakefile b/BaseTools/Source/C/GenFv/GNUmakefile index 872b981f6a94..843eb1b29152 100644 --- a/BaseTools/Source/C/GenFv/GNUmakefile +++ b/BaseTools/Source/C/GenFv/GNUmakefile @@ -14,6 +14,15 @@ include $(MAKEROOT)/Makefiles/app.makefile LIBS = -lCommon ifeq ($(CYGWIN), CYGWIN) - LIBS += -L/lib/e2fsprogs + LIBS += -L/lib/e2fsprogs -luuid +endif + +ifeq ($(LINUX), Linux) +ifndef CROSS_LIB_UUID + LIBS += -luuid +else + LIBS += -L$(CROSS_LIB_UUID) + BUILD_CFLAGS += -D__CROSS_LIB_UUID__ -I $(CROSS_LIB_UUID_INC) +endif endif diff --git a/BaseTools/Source/C/GenFv/GenFvInternalLib.c b/BaseTools/Source/C/GenFv/GenFvInternalLib.c index 29c3363a504d..3f982c529bc1 100644 --- a/BaseTools/Source/C/GenFv/GenFvInternalLib.c +++ b/BaseTools/Source/C/GenFv/GenFvInternalLib.c @@ -14,6 +14,15 @@ SPDX-License-Identifier: BSD-2-Clause-Patent // Include files // +#if defined(__FreeBSD__) +#include +#elif defined(__GNUC__) +#if !defined(__CROSS_LIB_UUID__) +#include +#else +#include +#endif +#endif #ifdef __GNUC__ #include #endif diff --git a/BaseTools/Source/C/GenFw/GNUmakefile b/BaseTools/Source/C/GenFw/GNUmakefile index 76cda7e7a3f6..2079835df7a4 100644 --- a/BaseTools/Source/C/GenFw/GNUmakefile +++ b/BaseTools/Source/C/GenFw/GNUmakefile @@ -18,6 +18,10 @@ ifeq ($(CYGWIN), CYGWIN) endif ifeq ($(LINUX), Linux) +ifndef CROSS_LIB_UUID LIBS += -luuid +else + LIBS += -L$(CROSS_LIB_UUID) +endif endif diff --git a/BaseTools/Source/C/GenSec/GNUmakefile b/BaseTools/Source/C/GenSec/GNUmakefile index 9f0844c1b8fe..db634e40e6e6 100644 --- a/BaseTools/Source/C/GenSec/GNUmakefile +++ b/BaseTools/Source/C/GenSec/GNUmakefile @@ -18,6 +18,10 @@ ifeq ($(CYGWIN), CYGWIN) endif ifeq ($(LINUX), Linux) +ifndef CROSS_LIB_UUID LIBS += -luuid +else + LIBS += -L$(CROSS_LIB_UUID) +endif endif diff --git a/BaseTools/Source/C/Makefiles/header.makefile b/BaseTools/Source/C/Makefiles/header.makefile index d369908a0948..f16b3297fc68 100644 --- a/BaseTools/Source/C/Makefiles/header.makefile +++ b/BaseTools/Source/C/Makefiles/header.makefile @@ -54,11 +54,11 @@ AS ?= $(CLANG_BIN)clang AR ?= $(CLANG_BIN)llvm-ar LD ?= $(CLANG_BIN)llvm-ld else ifeq ($(origin CC),default) -CC = gcc -CXX = g++ -AS = gcc -AR = ar -LD = ld +CC = $(GCC_PREFIX)gcc +CXX = $(GCC_PREFIX)g++ +AS = $(GCC_PREFIX)gcc +AR = $(GCC_PREFIX)ar +LD = $(GCC_PREFIX)ld endif LINKER ?= $(CC) ifeq ($(HOST_ARCH), IA32)