My target was a very small Linux on Amiga, so I decided to go for it with embedded profile, and some other features to considire:
- Use MUSL instead of GNU glibc
- Use BusyBox instead of fat user-land
- Use OpenRC for full extent (to substitute sysvinit as well)
- Omit Gentoo packaging, and compilers, and build dependencies all together
- Use OpenRC to switch features on-off
- Still wanted to use bash
To begin with, musl and glibc is mutually hate each other. My host is an ordinary x64 GNU Gentoo install, and according to my experience, cross-compiling still uses host's make.config. So, not to mess up my host, created a chroot (1st step) from a downloaded stage3 tarball.
I chose i686-pc-linux-musl, for two reasons: the target m68k architecture is also 32bit, and it is compiled and configured to use musl; no expected clash between C libraries here.
One thing to remember, when you chroot into i686 root, is to also run linux32 command, to switch environment, and calling conventions to 32 bit (will make some not so well written autoconfigs happy, and compile everything successfully). Also, since I have 32GB RAM, mounted tmpfs with confidence to /var/tmp to make emerges way faster, and bind mounted /var/db/repos/gentoo, /var/cache/distfiles from host (not to waste much disk).
An optional step (I like this in BTRFS), you create a snapshot of your chroot, if you created in a subvolum. Also, later it makes easier, if you just create a subvolume usr/m68k-unknown-linux-musl relative to your chroot:
$ btrfs subvol create usr/m68k-unknown-linux-musl
Update the chroot (inside) as usual: emerge -uaD @world, and it is a good environment to start.
The next thing one will need, is crossdev packaged: emerge -a crossdev.
Then, we need the crossdev tools for m68k (looked up the recent stable releases for other arch):
$ crossdev --b 2.37_p1 --g 10.3.0-r2 --k 5.10 --l 1.2.2-r3 -t m68k-unknown-linux-musl
This will take a while, but in the end, you should have a working cross-gcc and some starting folder structure under /usr/m68k-unknown-linux-musl, just like /etc/portage/ folder, with a minimal set included here.
Here comes the first magic: crossdev environment is linked to the embedded profile by default. But, you can change that, by providing a symlink to a different one. The only thing is: there is no m68k default musl profile. So, what I did, is actually not symlinking a profile, but created a directory make.profile under /etc/portage, and added 2 files:
And edited the parent file to contain this:
/var/db/repos/gentoo/profiles/default/linux/m68k/17.0
/var/db/repos/gentoo/profiles/default/linux/musl
/var/db/repos/gentoo/profiles/features/musl
Ofc. portage will complain every time about the profile is not being a symlink, but let's just ignore it. Also needed to fintune a bit the make.conf to contain the proper CPU arch already, and the accpet keywords (on top of the necessary use flags):
Time to build
Now it's time to call the crossbuilder:
$ m68k-unknown-linux-musl-emerge -auND --keep-going @world
This will start to cross-build a default install into usr/m68k-unknown-linux-musl
Get some rest, to be continued... Spoiler alert!! You will have some build errors, an no working emerge inside!
Some words about the accept keywords
One can observe, that packages tend to have architecture stable (fe: "amd64"), and unstable/testing (fe.: "~amd64") keywords. And there are some ancient architectures, where Gentoo doesn't maintain anymore stable packages. Some of them are: mips, alpha, and m68k is being one of them, all packages are marked as unstable, aka ~mips, ~alpha, ~m68k.
Now, the trouble is, if one defines unconditionally "~m68k", portage will install the latest, even untested, cutting edge version of the packages (even marked unstable on ~amd64, ~x86, ~arm!). This is a good way for asking some more trouble, then we need.
Fortunately, there is a "*" for accepting, which means: "the highest version of packages, for which exists at least one stable architecture". So, by defining "*" and removing "~m68k" from the picture (with "-~m68k"), we are practically targeting packages, which ones are already tried out, tested, and stable on at least a different platform. The chances are minimal, for collisions, etc... Also, you don't need to define package masks to constraint version, and update those manually, later an automatic update will most probably just work.