I am doing a project to modify the Linux kernel. I have a desktop Linux machine and I have no problem building kernel on it.
However, I am going on a trip and I want to
First, I agree that it's usually simpler to just use a Linux VM. That said, if you really want to do this, I have successfully compiled Linux kernel code using the procedure below.
Before you can even start, you may need to install the Linux source tree on a case-sensitive filesystem on your Mac. (the default HFS filesystem is case insensitive.) I won't cover that here, but a lot of people do this to compile the Android source tree, so you can use Google to find instructions.
First you'll need the following files to cross-compile a kernel on an OS X box (copy them from your known-working Linux VM to your local /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
Next you'll need malloc.h
to be in the expected location for a Linux system, so do:
sudo ln -s /usr/include/malloc/malloc.h /usr/include/malloc.h
Finally, you'll need to worry about whether or not the compiler installed on your system is suitable for building the Linux kernel. I have used this procedure for kernels compiled for Android, using an appropriate cross-compiler toolchain, but I'm not sure if you can successfully compile a Linux kernel with the default gcc
compiler on OS X (assuming you have the one that comes with Xcode...)
EDIT: You may also want to follow the steps pointed out in the bug linked in the comment above from "nmagerko", to ensure you have the correct dependencies, and the GNU version of sed
. In particular:
$ sudo port install libelf
$ sudo port install gsed
This is a common question (well, usually it's building on Windows, but the answer is the same).
Just don't do it. You're going to have so much trouble getting anything to build correctly, it's just not worth it. Use a virtual machine, as you said yourself. It's a little slower, but not all that much, and at least building will work correctly.
Kernel development is hard enough without introducing additional, unnecessary problems.
one update with arm64 kernel build on OSX 10.15.4 Catalina .
My intention is to natively build latest(5.7) arm64 kernel on macOS, and play it on qemu-system-aarch64 . btw, toolchain built from crosstool-ng.
1) Firstly follow above steps, to include some header files. I put them under my home folder
$ 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) second, some hack for host uuid code ,as the uuid_t type on mac is different as linux : scripts/mod/file2alias.c Remove uuid_t definition by one macro BUILD_ON_LINUX, and comment code in 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/
I've made symlinks to the missing OSX headers from the linux host ones and apparently it worked out well! In my setup I have sync'd the whole AOSP repo, which includes all prebuilts, but the ones that I am actually using to built the kernel are:
Clone them so that the following directory tree is valid:
<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/
Make sure you checkout the appropriate branch/tag, according to your Android target version.
Not sure if it's the proper way to do it, but putting the a bunch of linux headers in /usr/local/include
resolves all issues. Don't forget to chmod +x
the script.
#!/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
Kernel: arch/arm/boot/zImage-dtb is ready
AOSP
on macmac_version.mk
in build
to allow using 10.12.3 sdk)This works as of kitkat (didn't try earlier versions) - make -j8 ARCH=arm CROSS_COMPILE=arm-eabi- HOSTCFLAGS="-I ../external/elfutils/libelf"
This assumes the rest of the android build is set up as usual and the kernel directory is in the android build.
Here is an update for Android 6.0 Marshmallow and OSX 10.10 Yosemite. I have done several successful cross builds using this method. The only limitation is that I have only done these with the full AOSP source checked out.
I used brew's libelf to get a nice package managed elf library. This gets us the elf file we need to include, usr/local/opt/libelf/include/libelf/gelf.h
brew install libelf
But this will still throw errors on build if you symlink it to usr/local/include
as apparently some definitions are missing. So I stole the missing definitions from <kernel_source>/arch/arm/include/asm/elf.h
and created a shim include file:
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
That should be enough to get the build to complete. If anyone needs further information on this, I have a post that covers a full Android kernel build on OSX.