Skip to content

Commit

Permalink
BaseTools: Support custom library build for base tools on Linux ARM
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Liming Gao <[email protected]>
Cc: Bob Feng <[email protected]>
Cc: Yuwei Chen <[email protected]>
Signed-off-by: Kun Qin <[email protected]>
  • Loading branch information
kuqin12 authored and mergify[bot] committed Dec 20, 2024
1 parent 74bf7f5 commit 3c8016b
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 8 deletions.
93 changes: 91 additions & 2 deletions BaseTools/Edk2ToolsBuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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()
Expand Down
4 changes: 4 additions & 0 deletions BaseTools/Source/C/DevicePath/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

11 changes: 10 additions & 1 deletion BaseTools/Source/C/GenFv/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

9 changes: 9 additions & 0 deletions BaseTools/Source/C/GenFv/GenFvInternalLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
// Include files
//

#if defined(__FreeBSD__)
#include <uuid.h>
#elif defined(__GNUC__)
#if !defined(__CROSS_LIB_UUID__)
#include <uuid/uuid.h>
#else
#include <uuid.h>
#endif
#endif
#ifdef __GNUC__
#include <sys/stat.h>
#endif
Expand Down
4 changes: 4 additions & 0 deletions BaseTools/Source/C/GenFw/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

4 changes: 4 additions & 0 deletions BaseTools/Source/C/GenSec/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

10 changes: 5 additions & 5 deletions BaseTools/Source/C/Makefiles/header.makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 3c8016b

Please sign in to comment.