在Mac OS X上构建Linux内核

25

我的项目是修改Linux内核。我有一台桌面Linux机器,构建内核没有问题。

然而,我要外出旅行,并希望边走边工作。我只有一台MacBook。当我尝试构建Linux内核时,它抱怨找不到elf.h

我从互联网上下载了一个elf.h。现在它报错:NO ELF

我试着将整个/usr/include从我的Linux桌面复制过来,并将其设置为包含目录,但仍然会出现奇怪的错误,如"u8"未声明

在Mac上进行内核开发的标准方式是什么?我有一个在同一台Mac上运行Linux的虚拟机,用于测试修改后的内核。然而,我真的不想在上面构建内核,因为它有点慢。


这应该会有所帮助:http://code.google.com/p/android/issues/detail?id=2755 - nmagerko
1
你能发布一下你收到的确切错误吗?“NO ELF”并没有提供很多上下文。你是在什么时候看到这个错误的,之前发生了什么事情? - mpontillo
@Mike,我同意,那确实是错误所在,在我从互联网上复制了一个elf.h文件并将其添加到一个包含目录中以便make可以找到它之后出现的。我不知道如何使信息更具体。它发生得非常早。 - Alfred Zhong
@AlfredZhong,你调用哪个目标来获取“NO ELF”?你尝试过在make中添加详细标志以查看它正在做什么吗?我认为在Linux中你可以使用make V=1。另外,你为什么要从互联网上复制elf.h?我会从已知编译该内核的VM中复制它。 - mpontillo
就此而言,同样的问题也适用于在OSX上构建Yocto Linux。 - kolosy
6个回答

26

首先,我同意通常最简单的方法是使用Linux虚拟机。 话虽如此,如果你真的想做到这一点,我已经成功地使用以下程序编译了Linux内核代码。

在你开始之前,你可能需要在Mac上的区分大小写文件系统上安装Linux源代码树。(默认的HFS文件系统不区分大小写。) 我不会在这里涉及到这个问题,但很多人这样做是为了编译Android源代码树,所以你可以使用Google寻找相关的指导

要在OS X上交叉编译内核,你需要以下文件(从你已知可行的Linux VM复制到本地的/usr/include):

/usr/include/elf.h
/usr/include/features.h
/usr/include/bits/predefs.h
/usr/include/bits/wordsize.h
/usr/include/gnu/stubs.h
/usr/include/gnu/stubs-64.h

接下来,你需要将malloc.h放在Linux系统的预期位置,因此执行以下操作:

sudo ln -s /usr/include/malloc/malloc.h /usr/include/malloc.h

最后,你需要担心你系统上安装的编译器是否适用于构建Linux内核。我使用此过程为编译Android内核,使用适当的交叉编译工具链,但我不确定是否可以使用默认的 gcc 编译器在OS X上成功编译Linux内核(假设您使用的是随Xcode附带的编译器)


编辑:您可能还想按照“nmagerko”评论中链接的错误指出的步骤,确保您具有正确的依赖项和GNU版本的sed。特别是:

$ sudo port install libelf
$ sudo port install gsed

10

这是一个常见的问题(通常是在Windows平台上构建,但答案是相同的)。

不要尝试在本地构建内核。你将面临很多困难,并且它根本不值得。如你所说,使用虚拟机即可。速度可能会稍微慢一点,但至少构建过程可以正常工作。

内核开发已经很难了,不要引入额外的、不必要的问题。


2
我同意。我放弃了...我以为人们可能会想出方便的方法来解决它...结果证明是错误的。 - Alfred Zhong

4
这里有关于Android 6.0 Marshmallow 和OSX 10.10 Yosemite的更新。我已经使用这种方法进行了几次成功的交叉编译。唯一的限制是我只使用完整的AOSP源代码检出。
我使用brew的libelf获取一个不错的包管理的elf库。这使我们获得了所需的elf文件,usr/local/opt/libelf/include/libelf/gelf.h
brew install libelf

但是,如果你将它建立符号链接到usr/local/include,仍然会在构建时抛出错误,因为显然缺少一些定义。因此,我从<kernel_source>/arch/arm/include/asm/elf.h中窃取了缺失的定义,并创建了一个垫片包含文件:

cat <<EOT >> /usr/local/include/elf.h
#include "../opt/libelf/include/libelf/gelf.h"
#define R_386_NONE 0
#define R_386_32 1
#define R_386_PC32 2
#define R_ARM_NONE 0
#define R_ARM_PC24 1
#define R_ARM_ABS32 2
#define R_MIPS_NONE 0
#define R_MIPS_16 1
#define R_MIPS_32 2
#define R_MIPS_REL32 3
#define R_MIPS_26 4
#define R_MIPS_HI16 5
#define R_MIPS_LO16 6
#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */
#define R_PPC_ADDR32 1 /* 32bit absolute address */
#define R_PPC64_ADDR64 38 /* doubleword64 S + A */
#define R_SH_DIR32 1
#define R_SPARC_64 32 /* Direct 64 bit */
#define R_X86_64_64 1 /* Direct 64 bit */
#define R_390_32 4 /* Direct 32 bit. */
#define R_390_64 22 /* Direct 64 bit. */
#define R_MIPS_64 18
EOT

这应该足以让构建完成。如果任何人需要进一步了解,我有一篇涵盖在OSX上构建完整Android内核的文章


4

使用AOSP的预编译软件包编译内核

我已经从Linux主机中的缺失的OSX头文件创建了符号链接,而且似乎效果很好!在我的设置中,我已经同步了整个AOSP repo,其中包括所有的预编译软件包,但是我实际上用于构建内核的是以下两个:

克隆它们以使以下目录树有效:

<SOME-PATH>/prebuilts/
<SOME-PATH>/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8/
<SOME-PATH>/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.8/

请确保根据您的Android目标版本检出适当的分支/标签。

安装缺失的头文件

不确定这是否是正确的方法,但将一堆Linux头文件放在/usr/local/include中可以解决所有问题。不要忘记为脚本添加chmod +x权限。

install_headers.sh:

#!/bin/sh

PREBUILTS_DIR="<SOME-PATH>/prebuilts" # fill in the path here!

PREBUILT_GCC=$PREBUILTS_DIR"/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8"
KERNEL_HEADERS=$PREBUILT_GCC"/sysroot/usr/include"
HOST_HEADERS="/usr/local/include"

function install_header() {
    header=$1
    ln -s $KERNEL_HEADERS/$header $HOST_HEADERS/$header
}

# create symlinks for the missing headers
install_header elf.h
install_header features.h
# the following are folders (that contain headers)
install_header bits
install_header gnu
install_header linux
install_header asm
install_header asm-generic

构建内核

export PATH=<SOME-PATH>/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.8/bin:$PATH
export ARCH=arm
export SUBARCH=arm
export CROSS_COMPILE=arm-eabi-
# in this example it builds for N6
make shamu_defconfig
make -j8

看这里:

内核:arch/arm/boot/zImage-dtb 已经准备好了

我的配置

  • macOS Sierra 10.12.3
  • XCode: 使用 MacOSX10.11.sdk,可以在 Mac 上构建 AOSP
  • 目标设备:N6/shamu
  • AOSP 分支:Marshmallow(更新了 build 中的 mac_version.mk,以允许使用 10.12.3 sdk)

2

这在kitkat版本中可行(之前的版本未尝试)- make -j8 ARCH=arm CROSS_COMPILE=arm-eabi- HOSTCFLAGS="-I ../external/elfutils/libelf"

假设其余Android编译设置如常,并且内核目录位于Android构建中。


0

在OSX 10.15.4 Catalina上使用arm64内核构建进行了一次更新。

我的意图是在macOS上本地构建最新的(5.7)arm64内核,并在qemu-system-aarch64上运行它。顺便说一下,这个工具链是从crosstool-ng构建的。

1)首先按照上述步骤,包括一些头文件。我把它们放在我的主文件夹下

$ ls ~/usr/include/ -l

drwxr-xr-x 4 yupluo01 admin 128 May 4 16:47 bits

-rw-r--r-- 1 yupluo01 admin 177346 May 4 16:23 elf.h

-rw-r--r-- 1 yupluo01 admin 17079 May 4 16:23 features.h

drwxr-xr-x 4 yupluo01 admin 128 May 4 16:44 gnu

-rw-r--r-- 1 yupluo01 admin 6186 May 4 16:33 malloc.h

-rw-r--r-- 1 yupluo01 admin 2290 May 4 16:43 stdc-predef.h

2) 其次,关于主机uuid代码的一些hack,因为在Mac上的uuid_t类型与Linux上不同:scripts/mod/file2alias.c 通过一个宏BUILD_ON_LINUX删除uuid_t定义,并在do_tee_entry()中注释代码

3) 运行命令:make ARCH=arm64 HOSTCFLAGS="-I /usr/local/include -I ~/usr/include -I /usr/local/opt/openssl/include/ -L /usr/local/opt/openssl/lib/ -DBUILD_ON_LINUX=0" CROSS_COMPILE=aarch64-unknown-linux-gnu- O=out_arm64/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接