building Linux kernel on Mac OS X
Solution 1
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
Solution 2
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.
Solution 3
Compile Kernel using AOSP's prebuilts
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:
- Missing Linux headers: gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8
- Cross compiler: gcc/darwin-x86/arm/arm-eabi-4.8/
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.
Install the missing headers
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.
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
Build the kernel
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
Voila:
Kernel: arch/arm/boot/zImage-dtb is ready
My configuration
- macOS Sierra 10.12.3
- XCode: using MacOSX10.11.sdk, which allows building
AOSP
on mac - Target device: N6/shamu
- AOSP branch: Marshmallow (updated
mac_version.mk
inbuild
to allow using 10.12.3 sdk)
Solution 4
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.
Solution 5
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.
Related videos on Youtube
Alfred Zhong
Updated on May 10, 2020Comments
-
Alfred Zhong about 4 years
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 work on my way. I only have a MacBook. When I tried to build the Linux kernel, it complained that
elf.h was not found
.I download an elf.h from internet. Now it complains:
NO ELF
I tried copying the entire
/usr/include
from my Linux desktop, and set it as the include directory, and still get strange errors like"u8" not declared
What is the standard way of doing kernel development on Mac? I have a virtual machine running Linux on the same Mac, and it will be used to test the modified kernel. However, I don't really want to build kernel on it, as it is kinda slow.
-
nmagerko over 12 yearsThis should help: code.google.com/p/android/issues/detail?id=2755
-
mpontillo over 12 yearsCan you post the exact error you're getting?
NO ELF
doesn't provide a lot of context. When do you see that and what happened before that? -
Alfred Zhong over 12 years@Mike, I agree, that is the exact error, after I copy a elf.h file from internet and add it to a include directory so that make can find it. I don't know how to make it more informative. It happens pretty early.
-
mpontillo over 12 years@AlfredZhong, what make target do you invoke to get
NO ELF
? Have you tried adding a verbose flag tomake
to see what exactly it's doing; I think with Linux you usemake V=1
? Also, why did you copy elf.h from the internet? I'd copy it from your VM where compiling that kernel is known to work. -
ninjaSurfer over 9 yearsfwiw, the same issue applies to trying to build Yocto linux on osx as well.
-
-
Alfred Zhong about 12 yearsI agree. I gave up... I thought people might figured it out and came up with convenient way... And it turns out be to wrong.