{"id":15067242,"url":"https://github.com/chaimleib/maclfs","last_synced_at":"2025-04-10T13:54:46.607Z","repository":{"id":68082531,"uuid":"327881893","full_name":"chaimleib/maclfs","owner":"chaimleib","description":"Cross compile Linux on a Mac host","archived":false,"fork":false,"pushed_at":"2023-03-03T02:17:17.000Z","size":25,"stargazers_count":5,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-24T12:39:32.755Z","etag":null,"topics":["cross-compile","linux","linux-distribution","macos"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chaimleib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-08T11:19:02.000Z","updated_at":"2025-01-14T23:24:12.000Z","dependencies_parsed_at":"2024-09-29T11:43:11.574Z","dependency_job_id":"1cf3d935-6d73-4834-9a6a-da2560602096","html_url":"https://github.com/chaimleib/maclfs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaimleib%2Fmaclfs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaimleib%2Fmaclfs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaimleib%2Fmaclfs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaimleib%2Fmaclfs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chaimleib","download_url":"https://codeload.github.com/chaimleib/maclfs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248229454,"owners_count":21068896,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cross-compile","linux","linux-distribution","macos"],"created_at":"2024-09-25T01:18:32.395Z","updated_at":"2025-04-10T13:54:46.570Z","avatar_url":"https://github.com/chaimleib.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mac LFS\n\nThe goal of this project is to cross compile Linux on a Mac host. The only requirements are:\n\n* Xcode command line tools\n* [Homebrew](https://brew.sh)\n* [Paragon extFS for Mac](https://www.paragon-software.com/home/extfs-mac/)\n  ($39.95), or some other method of mounting and modifying an ext4 volume\n\nThis guide is based on [Linux from\nScratch](https://linuxfromscratch.org/view/lfs/), [Cross LFS - Embedded\nx86](https://clfs.org/view/clfs-embedded/x86/) and [dslm4515's\nMusl-LFS](https://github.com/dslm4515/Musl-LFS/blob/master/doc). I updated to\nthe latest packages as of 2021-01-08. The disk formatting tools were updated\n2021-09-24.\n\n# Set up environment\n\n\u003e `Parted` depends on glibc, which does not compile under macOS (dunno about\n\u003e musl). Compiling `gdisk` and `sgdisk` from source requires the brew packages\n\u003e `ossp-uuid` and `popt`.  However, rather than descend into the dependencies\n\u003e and make the project independent of `brew`, I favored speed at this stage,\n\u003e since the goal is to learn about Linux, rather than macOS.\n\n```bash\ngit clone https://github.com/chaimleib/maclfs\ncd maclfs\n```\n\nTo create the boot disk, we need `gptfdisk` and `e2fsprogs`. Building the\nheader files will require GNU's version of sed.\n\n```bash\nbrew install gptfdisk e2fsprogs gsed\n```\n\n\n# Creating the target disk\n\n```bash\n# create a blank 15GB file\ndd bs=4096 if=/dev/zero of=lfs.iso count=15728540\n\n# create loopback device from blank file, and remember the device name\n# In case you need to run this command again after a reboot and other\n# partitions exist already, the `; exit` to awk behaves like `head -n1` to grab\n# just the disk device name and not partition device names.\nlfsDev=$(hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount lfs.iso |\n  awk '{print $1; exit}')\n\n# partition the disk\n# -g                   Use GPT partitioning\n# -n 1::+200M -t ef00  First partition should be 200MB EFI\n# -n 2:: -t 8304       Rest should be ext4\n# -c 2:'LFS Disk'      Name the main partition\nsgdisk $lfsDev -g -n 1::+200M -t ef00 -n 2:: -t 8304\n```\n\nNow you have the necessary partition locations, but they aren't formatted yet.\n\n```bash\n# if you wish, verify the partitions.\nsgdisk -p $lfsDev\n\nDisk /dev/disk2: 31457080 sectors, 15.0 GiB\nSector size (logical): 512 bytes\nDisk identifier (GUID): 87317754-AF95-4293-83D0-1F9F128FAA71\nPartition table holds up to 128 entries\nMain partition table begins at sector 2 and ends at sector 33\nFirst usable sector is 34, last usable sector is 31457046\nPartitions will be aligned on 2048-sector boundaries\nTotal free space is 2014 sectors (1007.0 KiB)\n\nNumber  Start (sector)    End (sector)  Size       Code  Name\n   1            2048          411647   200.0 MiB   EF00\n   2          411648        31457046   14.8 GiB    8304  LFS Disk\n```\n\nNow, format the main partition. Homebrew stopped linking the e2fsprogs into the\nPATH, so specify the full path to the binary:\n\n```bash\n/opt/homebrew/opt/e2fsprogs/sbin/mke2fs -t ext4 -L lfsdisk ${lfsDev}s2\n```\n\nInstall extFS for Mac by Paragon Software ($39.95 or Free 10-day trial) to\nmount the disk image.\n\nhttps://www.paragon-software.com/home/extfs-mac/\n\nIf you have to reboot, use the following command to create the loopback device\nagain:\n\n```bash\nlfsDev=$( \\\n  hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount lfs.iso |\n  awk '{print $1; exit}')\n```\n\nThen, extFS should be able to mount it.\n\n\n# Build directory, Packages and Patches\n\nGive all users permissions to modify the disk:\n\n```bash\nLFS=/Volumes/lfsdisk\nsudo chmod 777 $LFS\n```\n\nCreate a directory that will hold the tools we need before we chroot or boot\nthe new linux system. In other words, the tools in this folder will be used\nfrom macOS.\n\n```bash\nmkdir -pv $LFS/cross-tools/{bin,lib/pkgconfig}\n```\n\nRemember installing `gsed` a while back? Make a link to it named `sed` in our\ncross-tools, so that it is available when we isolate our PATH variable:\n\n```bash\nln -s /usr/local/bin/gsed $LFS/cross-tools/bin/sed\n```\n\nCreate a bashrc:\n\n```bash\ncat \u003c\u003c \"EOF\" \u003e $MLFS/bashrc\nset +h\numask 022\nMLFS=$HOME/maclfs\nLFS=/Volumes/lfsdisk\nLC_ALL=POSIX\nPATH=$LFS/cross-tools/bin:$LFS/cross-tools/$LFS_TGT/bin:/bin:/usr/bin\nMANPATH=$LFS/cross-tools/share/man:$MANPATH\nPKG_CONFIG_PATH=$LFS/cross-tools/lib/pkgconfig\nexport MLFS LFS LC_ALL PATH MANPATH PKG_CONFIG_PATH\nunset CFLAGS\n\nexport LFS_HOST=\"$MACHTYPE-cross-darwin\"\nexport LFS_TGT=x86_64-mlfs-linux-musleabihf\nexport BUILD64=-m64\nexport LFS_CPU=k8-sse3\nexport LFS_ARCH=x86_64\nEOF\n```\n\nThen create and run a script to isolate your environment variables and load\nyour bashrc for you, make it executable, and run it. This reduces the chances\nthat variables from your host environment can affect your build.\n\n```bash\ncat \u003c\u003c \"EOF\" \u003e $MLFS/lfs.env\n#!/bin/bash\nexec env -i \\\n  HOME=$HOME \\\n  TERM=$TERM \\\n  PS1='\\u:\\w\\$ ' \\\n  /bin/bash --rcfile bashrc\nEOF\nchmod +x $MLFS/lfs.env\n$MLFS/lfs.env\n```\n\nIf you ever need to exit the new environment, type `exit`. To re-enter it, run `$MLFS/lfs.env`.\n\n# Cross toolchain\n\n## Prereqs for linux headers\n\nInstead of `wget`, use `curl -LJO` to download each URL in packages.txt and patches.txt.\n\n\u003e On 2021-09-24, I had HTTPS certificate issues with kernel.org and other\n\u003e source mirrors. For now, using `curl` works around it. Otherwise, I would\n\u003e have installed `wget` earlier, linked that and used it instead.\n\u003e\n\u003e `-LJO` must precede each URL sent to `curl`. `L` means to follow redirects,\n\u003e and `O` means to save a file with an automatically-determined name. However,\n\u003e the default is to figure out the name from the URL which is not always the\n\u003e original file name.  `J` says to use the name provided in the response\n\u003e headers.\n\nThe following commands assume that you have downloaded, decompressed and cd-ed\ninto the packages listed in packages.txt. Some packages also require\ncorresponding patches in patches.txt.\n\n## Linux (headers only)\nNow make the linux headers.\n\n```bash\nmake mrproper\nmake ARCH=$LFS_ARCH headers\nmake ARCH=$LFS_ARCH INSTALL_HDR_PATH=$LFS/cross-tools/$LFS_TGT headers_install\n```\n\n\u003e The above command failed to work on an HFS+ disk, and only succeeded inside the ext4 disk image.\n\u003e\n\u003e Since kernel version 5.5, `make headers_check` has been a no-op.\n\n## Binutils\n\n```bash\nmkdir -v build\ncd build\n../configure \\\n   --prefix=$LFS/cross-tools/$LFS_TGT \\\n   --target=$LFS_TGT \\\n   --with-sysroot=$LFS/cross-tools/$LFS_TGT \\\n   --disable-nls \\\n   --disable-multilib\nmake configure-host\nmake\nmake install\n```\n\n### Musl (headers only)\n\n```bash\n./configure --prefix=$LFS/cross-tools\nmake install-headers\ncp -r $LFS/cross-tools/include/{bits,{byteswap,elf,endian,features}.h} /usr/local/include\n\n# avoid \"typedef redefinition with different types\" error with macOS headers\nsed -i '/typedef unsigned _Int64 uint64_t/d' /usr/local/include/bits/alltypes.h\n```\n\n## GCC (static)\n\n```bash\nfor p in mpfr gmp mpc; do\n  tar -xf ../$p-*.tar.*\n  mv -v $p-* $p\ndone\nmkdir -v build\ncd build\n../configure \\\n  --prefix=$LFS/cross-tools \\\n  --build=$LFS_HOST \\\n  --host=$LFS_HOST \\\n  --target=$LFS_TGT \\\n  --with-sysroot=$LFS/cross-tools/$LFS_TGT \\\n  --disable-nls  \\\n  --disable-shared \\\n  --without-headers \\\n  --with-newlib \\\n  --disable-decimal-float \\\n  --disable-libgomp \\\n  --disable-libmudflap \\\n  --disable-libssp \\\n  --disable-libatomic \\\n  --disable-libquadmath \\\n  --disable-threads \\\n  --enable-languages=c \\\n  --disable-multilib \\\n  --with-mpfr-include=$PWD/../mpfr/src \\\n  --with-mpfr-lib=$PWD/mpfr/src/.libs \\\n  --with-arch=$LFS_CPU\n\n# remember -j8 as applicable\nmake all-gcc all-target-libgcc\nmake install-gcc install-target-libgcc\n```\n\n\u003e Attempting to include isl here will cause install to fail.\n\n## musl\n\n```bash\npatch -Np1 -i ../wcsnrtombs_cve_2020_28928_diff.txt\n./configure \\\n  CROSS_COMPILE=$LFS_TGT- \\\n  --prefix=/ \\\n  --target=$LFS_TGT\nmake\nDESTDIR=$LFS/cross-tools/$LFS_TGT make install\n```\n\n## GCC (final cross-compiler)\n\n```bash\nfor p in mpfr gmp mpc; do\n  tar -xf ../$p-*.tar.*\n  mv -v $p-* $p\ndone\n```\n\nNow prepare the build directory and make a symlink to enable POSIX threads.\n\n```bash\nmkdir -v build\ncd build\nmkdir -pv $LFS_TGT/libgcc\nln -s ../../../libgcc/gthr-posix.h $LFS_TGT/libgcc/gthr-default.h\n```\n\n```bash\n../configure \\\n  --prefix=$LFS/cross-tools \\\n  --build=$LFS_HOST \\\n  --host=$LFS_HOST \\\n  --target=$LFS_TGT \\\n  --with-sysroot=$LFS/cross-tools/$LFS_TGT \\\n  --disable-nls \\\n  --enable-languages=c \\\n  --enable-c99 \\\n  --enable-long-long \\\n  --disable-libmudflap \\\n  --disable-multilib \\\n  --with-arch=$LFS_CPU\nmake\nmake install\n```\n\n\u003e Do not attempt to also compile the c++ compiler at this stage. This leads to\n\u003e a dependency hell for files normally provided by glibc, but glibc has not\n\u003e been ported to work on macOS.\n\n## Findutils\n\nThe busybox Makefile requires us to have the GNU version of xargs, which is\nprovided by GNU Findutils.\n\n```bash\n./configure --prefix=$LFS/cross-tools\nmake\nmake install\n```\n\n## Pkg-config\n\nTo allow the menuconfig of the linux kernel to find our Ncurses library,\nPkg-config needs to be present to point the linker in the right direction.\n\n```bash\n./configure --prefix=$LFS/cross-tools  \\\n            --with-internal-glib       \\\n            --disable-host-tool        \\\n            --docdir=$LFS/cross-tools/share/doc/pkg-config-0.29.2\nmake\nmake install\n```\n\n## Ncurses\n\nWhen compiling the linux kernel, the menuconfig step requires Ncurses.\n\n```bash\nsed -i '/LIBTOOL_INSTALL/d' c++/Makefile.in\nsed -i s/mawk// configure\n```\n\nTo bootstrap the compilation, we need to build the tic program first.\n\n```bash\nmkdir build\ncd build\n../configure\nmake -C include\nmake -C progs tic\ncd ..\n```\n\nNow build the rest of Ncurses.\n\n```bash\n./configure --prefix=$LFS/cross-tools                \\\n            --mandir=$LFS/cross-tools/share/man      \\\n            --with-manpage-format=normal             \\\n            --with-shared                            \\\n            --without-debug                          \\\n            --without-ada                            \\\n            --without-normal                         \\\n            --enable-pc-files                        \\\n            --enable-widec\nmake\nmake TIC_PATH=$PWD/build/progs/tic install\necho \"INPUT(-lncursesw)\" \u003e $LFS/cross-tools/lib/libncurses.so\n```\n\nIn case there are libraries expecting the non-wide character libs, link them to\nthe wide character versions.\n\n```bash\nfor lib in ncurses form panel menu ; do\n    rm -vf                    $LFS/cross-tools/lib/lib${lib}.so\n    echo \"INPUT(-l${lib}w)\" \u003e $LFS/cross-tools/lib/lib${lib}.so\n    ln -sfv ${lib}w.pc        $LFS/cross-tools/lib/pkgconfig/${lib}.pc\ndone\n```\n\n\u003e Also, make sure that older programs looking for curses will be redirected to ncurses. Such programs would also require version 5, so we have to build again.\n\n\u003e ```bash\n\u003e rm -vf                     $LFS/cross-tools/lib/libcursesw.so\n\u003e echo \"INPUT(-lncursesw)\" \u003e $LFS/cross-tools/lib/libcursesw.so\n\u003e ln -sfv libncurses.so      $LFS/cross-tools/lib/libcurses.so\n\u003e make distclean\n\u003e ./configure --prefix=$LFS/cross-tools  \\\n\u003e             --with-shared    \\\n\u003e             --without-normal \\\n\u003e             --without-debug  \\\n\u003e             --without-cxx-binding \\\n\u003e             --with-abi-version=5 \n\u003e make sources libs\n\u003e cp -av lib/lib*.so.5* $LFS/cross-tools/lib\n\u003e ```\n\n# Building the LFS system\n\n## Build variables\n\n```bash\ncat \u003c\u003c EOF \u003e\u003e $MLFS/bashrc\n\nexport CC=\"${LFS_TGT}-gcc --sysroot=${LFS}\"\nexport CXX=\"${LFS_TGT}-g++ --sysroot=${LFS}\"\nexport AR=\"${LFS_TGT}-ar\"\nexport AS=\"${LFS_TGT}-as\"\nexport LD=\"${LFS_TGT}-ld --sysroot=${LFS}\"\nexport RANLIB=\"${LFS_TGT}-ranlib\"\nexport READELF=\"${LFS_TGT}-readelf\"\nexport STRIP=\"${LFS_TGT}-strip\"\nEOF\nsource $MLFS/bashrc\n```\n\n## LSB folder tree\n\nCreate the LSB (Linux Standard Base) folder structure.\n\n```bash\ncd $LFS\nmkdir -pv bin boot dev etc home lib/{firmware,modules}\nmkdir -pv mnt opt proc sbin srv sys\nmkdir -pv var/{cache,lib,local,lock,log,opt,run,spool}\ninstall -dv -m 0750 root\ninstall -dv -m 1777 {var/,}tmp\nmkdir -pv usr/{,local/}{bin,include,lib,lib64,sbin,share,src}\n```\n\n## Config files\n\nSet up config files.\n\nList of mounted files.\n\n```bash\nln -svf ../proc/mounts etc/mtab\n```\n\n```bash\ncat \u003e etc/passwd \u003c\u003c \"EOF\"\nroot::0:0:root:/root:/bin/ash\nbin:x:1:1:bin:/bin:/bin/false\ndaemon:x:2:6:daemon:/sbin:/bin/false\nadm:x:3:16:adm:/var/adm:/bin/false\nlp:x:10:9:lp:/var/spool/lp:/bin/false\nmail:x:30:30:mail:/var/mail:/bin/false\nnews:x:31:31:news:/var/spool/news:/bin/false\nuucp:x:32:32:uucp:/var/spool/uucp:/bin/false\noperator:x:50:0:operator:/root:/bin/ash\npostmaster:x:51:30:postmaster:/var/spool/mail:/bin/false\nnobody:x:65534:65534:nobody:/:/bin/false\nEOF\n```\n\n```bash\ncat \u003e etc/group \u003c\u003c \"EOF\"\nroot:x:0:\nbin:x:1:\nsys:x:2:\nkmem:x:3:\ntty:x:4:\ntape:x:5:\ndaemon:x:6:\nfloppy:x:7:\ndisk:x:8:\nlp:x:9:\ndialout:x:10:\naudio:x:11:\nvideo:x:12:\nutmp:x:13:\nusb:x:14:\ncdrom:x:15:\nEOF\n```\n\nRemember who last logged on.\n\n```bash\ntouch var/log/lastlog\nchmod -v 664 var/log/lastlog\n```\n\n## Libgcc\n\nInstall a copy of libgcc, and strip it to make it smaller.\n\n```bash\nif [ \"$LFS_ARCH\" = 'x86_64' ]; then\n  cp -v cross-tools/$LFS_TGT/lib64/libgcc_s.so.1 lib64\n  $LFS_TGT-strip lib64/libgcc_s.so.1\nelse\n  cp -v cross-tools/$LFS_TGT/lib/libgcc_s.so.1 lib\n  $LFS_TGT-strip lib/libgcc_s.so.1\nfi\n```\n\n## Musl\n\n```bash\npatch -Np1 -i ../wcsnrtombs_cve_2020_28928_diff.txt\n./configure \\\n  CROSS_COMPILE=$LFS_TGT- \\\n  --prefix=/ \\\n  --disable-static \\\n  --target=$LFS_TGT\nmake -j8\nDESTDIR=$LFS make install-libs\n```\n\n## Busybox\n\n```bash\nmake distclean\nmake ARCH=$LFS_ARCH defconfig\n```\n\nModify the default config to disable features that will not build under musl:\n\n```bash\nsed -i 's/\\(CONFIG_\\)\\(.*\\)\\(INETD\\)\\(.*\\)=y/# \\1\\2\\3\\4 is not set/g' .config\nsed -i 's/\\(CONFIG_IFPLUGD\\)=y/# \\1 is not set/' .config\nsed -i 's/\\(CONFIG_FEATURE_WTMP\\)=y/# \\1 is not set/' .config\nsed -i 's/\\(CONFIG_FEATURE_UTMP\\)=y/# \\1 is not set/' .config\nsed -i 's/\\(CONFIG_UDPSVD\\)=y/# \\1 is not set/' .config\nsed -i 's/\\(CONFIG_TCPSVD\\)=y/# \\1 is not set/' .config\n```\n\nThe make script failed for me while trying to remove the contents of\n`.tmp_versions/`. To let that command succeed, add a dummy file there for it to\nremove, and then compile the package.\n\n```bash\ntouch .tmp_versions/1\nmake ARCH=$LFS_ARCH CROSS_COMPILE=$LFS_TGT-\nmake ARCH=$LFS_ARCH CROSS_COMPILE=$LFS_TGT- CONFIG_PREFIX=$LFS install\ncp -v examples/depmod.pl $LFS/cross-tools/bin\nchmod -v 755 $LFS/cross-tools/bin/depmod.pl\n```\n\n## Iana-etc\n\n```bash\ncp services protocols $LFS/etc\n```\n\n\n# Make the system bootable\n\n## Create /etc/fstab\n\n```bash\ncat \u003e $LFS/etc/fstab \u003c\u003c \"EOF\"\n# file-system  mount-point  type   options          dump  fsck\nEOF\n```\n\n## Linux kernel\n\n```bash\nmake mrproper\nmake ARCH=$LFS_ARCH CROSS_COMPILE=$LFS_TGT- menuconfig\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchaimleib%2Fmaclfs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchaimleib%2Fmaclfs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchaimleib%2Fmaclfs/lists"}