Ubuntu 22.04系统搭建环境编译AOSP P

文章描述了在将Ubuntu从18.04升级到22.04以获取更高Linux内核版本5.19后,在编译sepolicy、framework和Androidkernel时遇到的错误。对于flex编译报错,解决方案是重新编译flex源码。patchoat报错是由于mmap系统调用的地址问题,通过添加MAP_FIXED_NOREPLACE标志解决。最后,Androidkernel编译中yylloc的重复定义和vdso32相关问题,分别通过删除定义和指定32位编译工具链路径解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

由于工作需要更新Linux kernel版本到5.16以后,查了一下当前Ubuntu 18.04只支持到5.4,自己下kernel代码来编译的话可能会有些现有驱动不兼容。

为了图方便,决定直接把Ubuntu升级到22.04.2,这样Linux kernel版本就直接到5.19了;

具体Ubuntu各个发行版本对应的Linux kernel支持情况,详见官网介绍或者Livepatch文档

但是,在将基础编译环境配置好后,同样的代码在22.04上遇到了几个报错,并且全网搜索结果不太好找到好的解决办法,遂整理如下:

编译sepolicy报错

报错信息:

flex-2.5.39: loadlocale.c:130: _nl_intern_locale_data: Assertion `cnt < (sizeof (_nl_value_type_LC_TIME) / sizeof (_nl_value_type_LC_TIME[0]))' failed.
Aborted (core dumped)

解决方法:
使用源码重新编译一个flex替换掉:

# 进入flex目录
cd prebuilts/misc/linux-x86/flex/
# 解压源码,注意这里一定要建一个目录,否则解压出来的目录名会覆盖掉flex-2.5.39这个二进制文件(同名),不利于后面做替换
mkdir flex-2.5.39_src
tar xzvf flex-2.5.39.tar.gz -C ./flex-2.5.39_src
cd flex-2.5.39_src/flex-2.5.39/
# 默认配置方式编译
./configure && make
# 替换掉源码中的二进制
mv flex ../../flex-2.5.39
# 返回flex目录,清理解压出来的目录,同时清除编译中间文件
cd ../../
git clean -fd -- ./
# 回到Android编译根目录
cd ../../../../

编译framework报错

报错信息:

patchoatd E 06-21 15:22:26 844380 844380 image_space.cc:1761] Could not create image space with image file 'out/target/product/blueline/dex_bootjars/system/framework/boot.art'. Attempting to fall back to imageless running. Error was: Failed to mmap at expected address, mapped at 0x7fe5d0000000 instead of 0x705db000
patchoatd E 06-21 15:22:26 844380 844380 image_space.cc:1761] Attempted image: out/target/product/blueline/dex_bootjars/system/framework/boot-framework.art
patchoatd E 06-21 15:22:26 844380 844380 runtime.cc:1290] Dex file fallback disabled, cannot continue without image.
patchoatd E 06-21 15:22:26 844380 844380 patchoat.cc:485] Unable to initialize runtime
ninja: build stopped: subcommand failed.

问题原因:
报错指出,mmap系统调用返回的内存起始地址与传下去的建议地址值不一致。
实际上,这个建议值在Linux kernel 5.18(Host端,即PC或工作站端)及其以后,基本是被无视掉了,导致每次创建的内存地址值,跟建议值都不一样,从而报错,而在Linux kernel 5.17及其以前的版本,建议值通常都会被接受,并按照该地址申请内存;

解决方式:
mmap系统调用时,flag添加MAP_FIXED_NOREPLACE标志位;

代码片段:

//art/runtime/mem_map.cc
MemMap* MemMap::MapFileAtAddress(uint8_t* expected_ptr,
                                 size_t byte_count,
                                 int prot,
                                 int flags,
                                 int fd,
                                 off_t start,
                                 bool low_4gb,
                                 bool reuse,
                                 const char* filename,
                                 std::string* error_msg) {
  ...
  if (reuse) {
    // reuse means it is okay that it overlaps an existing page mapping.
    // Only use this if you actually made the page reservation yourself.
    CHECK(expected_ptr != nullptr);
    DCHECK(error_msg != nullptr);
    DCHECK(ContainedWithinExistingMap(expected_ptr, byte_count, error_msg))
        << ((error_msg != nullptr) ? *error_msg : std::string());
    flags |= MAP_FIXED;
//Add begin @{
#if !defined(ART_TARGET)
  } else if (expected_ptr) {
#define MAP_FIXED_NOREPLACE 0x100000
    flags |= MAP_FIXED_NOREPLACE;
#endif
//@}
  } else {
    ...
  }
  ...
}

参考资料:这里的问题讨论这里的修改方法

编译Android kernel报错

yylloc重复定义

报错信息:

/usr/bin/ld: scripts/dtc/dtc-parser.tab.o:(.bss+0x10): multiple definition of `yylloc'; scripts/dtc/dtc-lexer.lex.o:(.bss+0x0): first defined here

这个应该是编译环境版本变化导致的,从日志可以知道,编译scripts/dtc/dtc-parser.tab.o时,发现yylloc已经在scripts/dtc/dtc-lexer.lex.o中定义过了,因此报了重复定义的错误;
解决思路应该就是在scripts/dtc/dtc-parser.tab.o去掉yylloc的定义;

代码片段:

//${kernel_src_top}/scripts/dtc/dtc-parser.tab.c_shipped
 /* The semantic value of the lookahead symbol.  */
 YYSTYPE yylval;
 /* Location data for the lookahead symbol.  */
 //Removed begin @{
 //YYLTYPE yylloc
 //@}
 # if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
   = { 1, 1, 1, 1 }
 # endif

/…//bin/as: unrecognized option ‘-mfloat-abi=soft’

在解决完了上面yylloc重复定义的问题后,再次编译kernel,会出现如下报错:
报错信息:

 Building kernel
make: Entering directory '/home/ryan/projects/zsui-aosp-p-dev/out/target/product/blueline/obj/KERNEL_OBJ'
  ...
  VDSOC32   arch/arm64/kernel/vdso32/vgettimeofday.o
  VDSOA32   arch/arm64/kernel/vdso32/sigreturn.o
/..//bin/as: unrecognized option '-mfloat-abi=soft'
clang-5.0: error: assembler command failed with exit code 1 (use -v to see invocation)
make[3]: *** [/home/ryan/projects/zsui-aosp-p-dev/kernel/private/msm-google/arch/arm64/kernel/vdso32/Makefile:144: arch/arm64/kernel/vdso32/sigreturn.o] Error 1
make[3]: *** Waiting for unfinished jobs....
/..//bin/as: unrecognized option '-mfloat-abi=soft'
clang-5.0: error: assembler command failed with exit code 1 (use -v to see invocation)
make[3]: *** [/home/ryan/projects/zsui-aosp-p-dev/kernel/private/msm-google/arch/arm64/kernel/vdso32/Makefile:142: arch/arm64/kernel/vdso32/vgettimeofday.o] Error 1
make[2]: *** [arch/arm64/Makefile:242: vdso_prepare] Error 2
make[1]: *** [Makefile:152: sub-make] Error 2
make: *** [Makefile:24: __sub-make] Error 2
make: Leaving directory '/home/ryan/projects/zsui-aosp-p-dev/out/target/product/blueline/obj/KERNEL_OBJ'
ninja: build stopped: subcommand failed.

问题原因:
vdso32这个目标需要使用gcc交叉编译,并且是使用32位的编译工具链,但是当前Android kernel编译规则并未指定工具链的路径,导致在Ubuntu 22.04上无法找到正确的as二进制执行文件进行汇编;

解决方法:
gcc编译32位目标时,添加–prefix与–gcc-toolchain两个参数指定,这样会找到正确的as二进制执行文件进行汇编;

代码片段:总共需要修改两个文件

//${kernel_src_top}/arch/arm64/Makefile
   ...
   else ifeq ($(cc-name),clang)
     export CLANG_TRIPLE_ARM32 ?= $(CROSS_COMPILE_ARM32)
     export CLANG_TARGET_ARM32 := --target=$(notdir $(CLANG_TRIPLE_ARM32:%-=%))
     # Added @{
     export GCC_TOOLCHAIN32_DIR := $(dir $(shell which $(CROSS_COMPILE_ARM32)ld))
     export GCC_TOOLCHAIN32 := $(realpath $(GCC_TOOLCHAIN32_DIR)/..)
     export CLANG_PREFIX32 := --prefix=$(GCC_TOOLCHAIN32_DIR)
     export CLANG_GCC32_TC := --gcc-toolchain=$(GCC_TOOLCHAIN32)
     # @}
     export CONFIG_VDSO32 := y
     vdso32 := -DCONFIG_VDSO32=1
   else ifeq ($(shell which $(CROSS_COMPILE_ARM32)$(cc-name) 2> /dev/null),)
   ...
//${kernel_src_top}/arch/arm64/kernel/vdso32/Makefile
...
 ifeq ($(cc-name),clang)
   # Modified @{
   # Original code:
   # CC_ARM32 := $(CC) $(CLANG_TARGET_ARM32) -no-integrated-as
   CC_ARM32 := $(CC) $(CLANG_TARGET_ARM32) -no-integrated-as $(CLANG_GCC32_TC) $(CLANG_PREFIX32)
   # @}
 else
   CC_ARM32 := $(CROSS_COMPILE_ARM32)$(cc-name)
 endif
...

参考资料:参考这笔提交

### 配置Ubuntu 22.04上的Android编译环境 #### 准备工作 为了确保系统的软件包是最新的,在开始之前应当更新现有的软件包列表并安装必要的工具和库。 ```bash sudo apt-get update && sudo apt-get upgrade -y ``` #### 安装依赖项 对于构建AOSP来说,除了基本的Java JDK之外还需要一些其他的依赖项。可以按照如下命令来一次性安装这些必需品: ```bash sudo apt-get install git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 libncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig openjdk-11-jdk -y ``` 上述命令不仅包含了OpenJDK 11的安装[^2],还涵盖了其他用于支持源码编译的重要组件。 #### 获取AOSP源代码 创建一个合适的工作目录,并从中克隆官方仓库中的最新版AOSP源代码。这里假设选择了`~/work/android/aosp/`作为工作路径。 ```bash mkdir -p ~/work/android/aosp/ cd ~/work/android/aosp/ repo init -u https://android.googlesource.com/platform/manifest repo sync ``` #### 初始化构建环境 进入解压后的文件夹内执行初始化脚本,这一步骤是为了设定好后续编译过程中需要用到的各种变量与函数定义。 ```bash source build/envsetup.sh ``` 选择合适的编译目标,例如针对SDK镜像进行调试版本(`userdebug`)的编译: ```bash lunch sdk_car_x86_64-userdebug ``` #### 编译过程 最后就是实际的编译操作了,可以根据机器性能调整线程数(-j参数),一般建议设置为CPU核心数量加上一或两倍于其数目以充分利用硬件资源。 ```bash make -j$(nproc --all) ``` 整个编译流程可能耗时较长,具体取决于所选的目标以及计算机本身的处理能力[^3]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值