在 Mac OS X 上构建 Linux 内核

Posted

技术标签:

【中文标题】在 Mac OS X 上构建 Linux 内核【英文标题】:building Linux kernel on Mac OS X 【发布时间】:2012-04-18 14:41:44 【问题描述】:

我正在做一个修改 Linux 内核的项目。我有一台桌面 Linux 机器,在上面构建内核没有问题。

但是,我要去旅行,我想按我的方式工作。我只有一台 MacBook。当我尝试构建 Linux 内核时,它抱怨 elf.h was not found

我从网上下载了一个 elf.h。现在它抱怨:NO ELF

我尝试从我的 Linux 桌面复制整个 /usr/include,并将其设置为包含目录,但仍然出现 "u8" not declared 之类的奇怪错误

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

【问题讨论】:

这应该会有所帮助:code.google.com/p/android/issues/detail?id=2755 你能发布你得到的确切错误吗? NO ELF 没有提供很多上下文。你什么时候看到的?在那之前发生了什么? @Mike,我同意,这是确切的错误,在我从 Internet 复制 elf.h 文件并将其添加到包含目录以便 make 可以找到它之后。我不知道如何使它更具信息性。它发生得很早。 @AlfredZhong,你调用什么目标来获取NO ELF?您是否尝试向make 添加详细标志以查看它到底在做什么?我认为对于 Linux,您使用 make V=1?另外,你为什么从网上复制elf.h?我会从你的 VM 中复制它,在那里编译该内核是已知的。 fwiw,同样的问题也适用于尝试在 osx 上构建 Yocto linux。 【参考方案1】:

首先,我同意只使用 Linux 虚拟机通常更简单。也就是说,如果您真的想要这样做,我已经使用以下过程成功编译了 Linux 内核代码。

在开始之前,您可能需要在 Mac 上的区分大小写的文件系统上安装 Linux 源代码树。 (默认的 HFS 文件系统不区分大小写。)我不会在这里介绍,但是很多人这样做是为了编译 Android 源代码树,所以you can use Google to find instructions。

首先,您需要以下文件来在 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 编译的内核,使用适当的交叉编译器工具链,但我不确定你是否可以使用 OS X 上的默认 gcc 编译器成功编译 Linux 内核(假设你有一个自带Xcode...)


编辑:您可能还想按照上面“nmagerko”评论中链接的错误中指出的步骤操作,以确保您拥有正确的依赖关系,以及@987654327 的GNU 版本@。特别是:

$ sudo port install libelf
$ sudo port install gsed

【讨论】:

【参考方案2】:

这是一个常见问题(嗯,通常它是在 Windows 上构建的,但答案是一样的)。

只是不要这样做。您将很难正确构建任何东西,这是不值得的。 正如您自己所说,使用虚拟机。它有点慢,但不是那么多,至少构建可以正常工作。

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

【讨论】:

我同意。我放弃了...我认为人们可能会想出办法并想出方便的方法...结果证明是错误的。【参考方案3】:

这是针对 Android 6.0 Marshmallow 和 OSX 10.10 Yosemite 的更新。我已经使用这种方法完成了几次成功的交叉构建。唯一的限制是我只在签出完整的 AOSP 源代码的情况下完成了这些操作。

我使用 brew 的 libelf 获得了一个不错的包管理精灵库。这为我们提供了需要包含的 elf 文件,usr/local/opt/libelf/include/libelf/gelf.h

brew install libelf

但是,如果您将其符号链接到usr/local/include,这仍然会在构建时引发错误,因为显然缺少一些定义。所以我从<kernel_source>/arch/arm/include/asm/elf.h 中窃取了缺失的定义并创建了一个 shim 包含文件:

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

这应该足以完成构建。如果有人需要这方面的更多信息,我有一个post,它涵盖了在 OSX 上构建的完整 Android 内核。

【讨论】:

【参考方案4】:

使用 AOSP 的预构建编译内核

我已经从 linux 主机中为丢失的 OSX 标头创建了符号链接,显然效果很好!在我的设置中,我同步了整个AOSP repo,其中包括所有prebuilts,但我实际用于构建内核的是:

缺少 Linux 标头:gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8 交叉编译器:gcc/darwin-x86/arm/arm-eabi-4.8/

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

<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)

【讨论】:

【参考方案5】:

这适用于 kitkat(未尝试早期版本)-make -j8 ARCH=arm CROSS_COMPILE=arm-eabi- HOSTCFLAGS="-I ../external/elfutils/libelf"

这假设 android 构建的其余部分像往常一样设置,并且内核目录位于 android 构建中。

【讨论】:

【参考方案6】:

在 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/

【讨论】:

以上是关于在 Mac OS X 上构建 Linux 内核的主要内容,如果未能解决你的问题,请参考以下文章

苹果的mac os是基于linux内核编写的吗?

如何在 Mac OS X 上发现*逻辑*核心的数量?

[架构之路-28]:目标系统 - 系统软件 - Linux OS内核功能架构图解内核构建内核启动流程

OS X 内核恐慌诊断。如何翻译回溯地址

Linux基础入门

在 Mac OS X 上使用 Eclipse CDT 调试远程 Linux 应用程序