But very recently I've been introduced to RetroPie, a distro for Raspberry Pi (raspi) which is dedicated to turning your raspi to a retro gaming machine. Since I have a dusty Pi3 laying around doing nothing (which I was supposed to use for testing Mick's Raspbian Buster but never got my lazy bum off to actually do it - sorry Mick!), I reckon, why not give it a try. If it doesn't work all I wasted is a couple of minutes downloading ~800MB image and couple of minutes "dd"-ing it.
As it turned out, it worked the first time around. Once the SD card as prepared, I put it inside the raspi, hooked the raspi to my TV, and then turned the raspi on. I was instantly asked to configure my controller (I didn't have one, but no problem, retropie accepts keyboard too). I configured the optional wifi setup (I didn't have to do it, but I wanted to try its samba feature). Then all I needed to do was to install the games (which I can install via USB, SFTP, or Samba). No stupid questions, no hassle, no config file. It's all ready to use. Most of the popular emulators were already included, and those that don't, are literally available for installation, a few clicks away.
With retropie on it, the raspi has been magically turned into a retro gaming machine. In the beginning I didn't believe that the raspi had enough muster to pull up a decent emulation, but I was pleasantly proven wrong. Most emulators worked well. Some had a few stutters every once a while but it was nothing to fret about.
The display quality was good, too. Retro games were notorious for displaying low-res pixelated images on today's high-res TV, but the emulators included in retropi had a few tricks up their sleeve to make the images sharper. I'm not surprised about that (after all I compiled some of those for Fatdog64 too) but what surprised me that the little raspi could pull off the enhanced graphics too. Well again not all emulators and not all games, but as I said, nothing to fret about.
Now, I have FatdogArm, Fatdog's variants that runs on ARM machines, the raspi included. If I really want to, I could, in theory, build and package all these myself too, producing a custom FatdogArm build that does what retropie does. All the software used in retropie is FOSS software. The standard release of FatdogArm was built to run as a "desktop-replacement" OS, but of course at its very core it was designed to be modded to produce a build that met specific needs. Making a retro gaming machine would be one of those.
But of course, why bother? The folks who makes retropie does a very good job, and the result is a very polished retro gaming software. Unless you try very very hard, you won't even know that beneath all the pretty faces, it runs Raspian Buster Linux. Rather than spending thankless hours building software on FatdogArm so it can become retropie wannabe, I may as well use retropie as is and start gaming with my kids
Anyway. In case you want to try retropie and don't have raspi, there is no need to fret and there is no need to fork out extra dollars too. While originally designed for raspi (all varians from pi 0/1/2/3/4), today's retropie supports other platforms: Odroid C1/C2, Odroid XU3/XU4, as well as standard PC! Yes, standard PC. You can use your old laptop, old desktop, NUC if you have one, etc basically any PC. The details are all on their website, if you're interested, go ahead and check it out.
Meanwhile, I've got a few games I need to catch up.
Disclaimer: I am not affiliated with retropie or any of its developers. In fact I wasn't aware that it exists until last week. I'm writing this to share with fellow retro gamers who aren't aware of retropie.
Comments - Edit - Delete
One of those formats is SPC. There are plenty of players for Windows (mostly plugins to popular music players), but standalone players for Linux are few and far between.
There is this player called AudioOverload but it is closed-source and output only to /dev/dsp. It does have a nice interface and supports many different video game formats, not only SPC.
The older version of gstreamer (0.10 branch) has a decoder in their 'bad plugins' collection called "GstNsfDec" which apparently can be used to decode SPC file (I haven't tested) - but do I really want to install the entire train of old gstreamer libs just to do that?
Then I found this vspcplay is an SDL-based player which is really nice and full featured; unfortunately the emulation isn't accurate; it sounds different from what I heard in the game and it eats 100% of one of my CPU core when running it.
Finally I found this one: SPC-PLAYER, a CLI player for SPC but unfortunately like AudioOverload it also outputs to /dev/dsp (and other OSS devices).
The problem with outputting to /dev/dsp is that whatever program is outputting the sound takes an exclusive use of the soundcard. I cannot play anything if I have my web brower open and one of its tab is pointing to youtube (even if nothing is being played), because the browser keep the sound access open and this prevents other programs to access /dev/dsp.
The only way to make work nicely is to use ALSA, which comes with built-in mixer (dmix) allowing multiple programs to use the sound card at the same time.
So I've written a simple patch for SPC-PLAYER to use libao, a very nice sound output library that enables us to output to a variety of output devices (ALSA, OSS< Pulse, etc) with exactly the same, simple API. Nice.
Well, if you're interested, you can find the patch in my patches page.
Note that SPC-PLAYER compiles in 32-bit only due to its extensive usage of x86 assembly in its APU emulation.
EDIT: and just after I spent the effort to create the patch, I found ZXTune which is a full-fledged multi-format chiptune player which includes support for SPC and many other formats! You know, you can't guess by its name alone (ZXTune - it plays only sounds for ZX Spectrum? Come on ...). It's open source and binary is provided, too! Works out of the box and supports the formats I'd love to play. The program comes in GUI flavours (Qt) and CLI, with only minimal dependencies needed (the rest of the libs needed were compiled statically with the binary).
So go ahead and use that instead.
EDIT: After finding ZX-Tune, JakeSFR informed me that deadbeef music player can also play SPC files.
Interesting. I looked into that, and found that deadbeen uses a library called "game music player", also known as libgme, to do that. And I found out ZXTune uses the same library too!
The library also has a simple "sample player" which uses SDL for output and hence is not affected by the "OSS problem".
You can get libgme from here.
That probably explains why nobody bothers to patch SPC-PLAYER, but that's okay. At least now I know how to use libao for my future projects
Comments - Edit - Delete
As the previous blog entry indicates, however, John de Murga, the owner of the Puppy Linux forum, sadly passed away, and the original Puppy Linux forum went down (for a time).
Behind the scenes people are frantically working to bring it up, but there are also efforts to setup a replacement forums, including one by rockedge.
By now, both efforts have been fruitful: the old forum has been resurrected and the rockedge forum has flourished with old and new members (re-)joining it.
The stewards of Puppy Linux has decided that the old forum will continue in read-only mode as archives, while rockedge forum will take over as the new Puppy Linux forum.
Rockedge has graciously offered a section of the forum specifically for Fatdog, for which we are very grateful.
After some internal discussions, we have decided to take the offer and continue the tradition of piggybacking on Puppy Linux forum. All of Fatdog team members have now re-joined there as well.
For your reference:
The new forum address: https://forum.puppylinux.com (Fatdog posts will be in the Fatdog section)
The old (archived) forum (in case you need to review/check old postings for older version of Fatdogs): http://oldforum.puppylinux.com (Fatdog posts are in the Puppy Projects section)
We'll see you there in the new forum!
Comments - Edit - Delete
If you use Fatdog64, you will know that we hosted our support threads on the same forum.
But my involvement with the Puppy Linux forum dates back well before then. I started browsing the forum when I was still a Windows user back in 2006; and joined in 2007 when I was converted into Puppy Linux user - and had been a regular on the forum ever since. Until the forum went down in early July 2020.
But in all my years being John's forum, I don't really know John Murga. Not personally. Never met him. Never spoke with him. Not even knowing how he looked like - well, not until a few days before I wrote this. Not through my fault though, I only know bits and pieces that he himself chose to share, for he himself claimed to be 'the man of mystery'.
He and his work, however, left an indelible mark on my life. It was such a simple work. Setting up an online forum. What was so difficult about it? Get a web-hosting site. Click a button, and you've got a forum and up running. Easy. Everyone can do it, right?
No. Not every one can do what John did.
The forum he set up was the forum where I spent lots of my past life on. Where I got help when I started and when I stumbled. Where I, eventually, helped others as I became proficient enough. Where I, unexpectedly, met and became friends with people in the real world.
All of these because he had the tenacity to keep the forum going for 15+ years; and let the forum to govern itself instead of strict policing found in many others. He even had the magnanimity to allow people to post links of competing projects and forums. This was one of the factors why so many people stayed on and the forum grew to become the melting pot of folks from all walks of life, sharing the same interest - Puppy Linux, and Linux in general.
So it was great shock and sadness that I learn of his passing recently in May 2020. I was even more stunned to know that he had left a young family - a daughter and twins who were born shortly after his passing. I have young children myself, I could not even begin to contemplate how it must have felt, to be left so soon, and so suddenly.
Nevertheless, I would like offer a prayer of hope for whom that John's family, that John had left a legacy that not many people could manage to do: to change the life of thousands, if not then ten thousands. John had left many friends that he himself probably didn't know. I was one of them, one among the thousands. For us, he is a hero. In every sense of the word.
Goodbye, John, and all blessings in your next journey.
You will be missed, but not forgotten.
Eulogy from 01micko, the current steward of Puppy Linux
Eulogy from Barry Kauler, the creator of Puppy Linux
Comments - Edit - Delete
Here are a few major things that has been going on, in no particular order.
1. Puppy Linux forum user ICPUG has indicated possible issues with Fatdog savefile residing on an NTFS partition, especially partition shared with Windows. This is due to the way Fatdog uses ntfs-3g: it runs with full permission control enabled. It makes NTFS behaves like POSIX filesystem and we can use it for save directory (not only save file), but on the other hand it makes Windows complain about not-granted access each time the partition needs to be accessed from Windows.
Based on this feedback, we have added "ntfsnoperm" boot parameter to disable that permission control. When this parameter is used, ntfs-3g is run without permission: it would behave just like FAT filesystem (all files and directories are owned by a given uid/gid specified at mount time). It would not be possible to use a save directory on NTFS, but at least the permission wouldn't be touched and Windows will stop complaining.
2. The same ICPUG also found an old bug related to the above: where the user "spot" would be unable to access a Downloads folder that has been relocated to a save partition if the save partition is NTFS. This has been fixed.
3. Fatdog has long supported btrfs. The kernel is built to support btrfs and we have the complete btrfs-progs included; and nominally we support having save directory on btrfs. But this does not actually work; because "aufs" - the unifying filesystem layer that we use to make the magic happen, does not support btrfs the way it supports other filesystem. For the techie: the problem is that aufs cannot have its xino file inside btrfs. It has to be somewhere else.
Thanks for our team member SFR (his Puppy Forum name), this was brought to attention and he shared a fix too. The fix was tested, worked on, and finally merged: now, save directory will work seamlessly on btrfs-formatted partition.
4. The original motivation for doing (3) above was actually to attempt to use a compressed filesystem. This has been a particular interest for me for years. The last time I explored this (a couple of years ago), btrfs wasn't mature enough and there was no other native writable filesystem with compression support. Sure, there were native filesystem with compression support - but they were all readonly (squashfs being the most popular one). Sure, a couple of FUSE filesystems support compression too (in fact it's their number one feature), but they were not actively maintained and being done in userspace, it was slow. I never got enough motivation to implement them properly with Fatdog.
Btrfs finally changed this equation. By now it should be considered mature enough (although probably not as hyped as before), and it supports compression as well. In fact, it supports three different compression algorithms: lzo, lz4 and zstd.
So as we fixed btrfs save directory support, we grafted compression support too. If the kernel parameter "btrfscompress" is specified, the compression support for btrfs will be enabled, using the algorithm specified on that parameter. This has been tested to work wonderfully and using zstd, the compression rate is about 30% on average.
5. We have an update on the in-house "screencaster" application (a program record the video of the display). It now has the ability to take repeated screen capture, better quality video, among other things.
6. Step, another member of Fatdog team, has also revamped the "Samba Shares" application. It has been re-factored and is heavily tested to work across different Samba servers (different Windows versions, etc).
7. We have also fixed a long-standing bug when running Fatdog with RAM layer operation, which can cause inconsistencies if the system is heavily used (a lot of filesystem access) when the "merge down" process happens. SFR found this to be irritating enough to find a solution that works better; and this got incorporated into Fatdog.
An additional feature was also added: the ability to remove whiteouts if they don't hide any files on the lower SFS layers, but not activated by default due to possible conflict with multisession operation (we haven't tested the interaction yet).
8. We also include the "updater script" which re-enable VLC's ability to play youtube video directly, without having to update VLC itself. The script is called update-vlc-playlist-luac.sh. SFR found this script.
And of course, many other smaller bugfixes and feature addition, as well as adding and updating packages on the repo as well.
So when will we have a new release? Well, it will be released when it is released.
Comments - Edit - Delete
Release Notes and Forum announcements
Can't believe that Fatdog is coming to its twelfth year.
Download locations: ibiblio.org, aarnet, uoc.gr, nluug.nl.
Comments - Edit - Delete
CSVfix is a tool for manipulating CSV files. Along with the usual column re-ordering and filtering, CSVfix offers a powerful per-cell data transformation using a simple expression language, as well as regular-expression for string matching and editing. And if this is not enough, CSVfix can execute external process - for every cell that needs to be processed. And oh, it's available for Windows too!
I find this tool to be very handy in what I need to do, so when I encountered a bug in its regex processing (for its "edit" command), I immediately checked if there is any updates to this tool. Unfortunately, its development seems to have ceased in 2015; and no other people seem to have picked up the development (I did find some forks, but they were all older copies from when it was still hosted in google code).
So I set out to figure out about the problem and hopefully rectify it. I found that the problem was in its regex library, which was a home-grown library (apparently adapted from an algorithm book). It is 2020 as of this time of writing, and C++ now comes with its own STL regex library (std::regex). I decided to rip off the custom regex lib and replace it with the STL regex instead, while keeping the rest of the class interface identical, therefore no other part of the code needed to be changed. This instantly fixed the problem, and as a bonus, now we can use ECMAScript-compatible regex instead of just the basic regex.
Later, I found out that the "exec" command also had a bug (the flag "-ix" did not work properly), so I traced this and fixed it too.
Oh, and during the process, I tried to run its testsuite - and while most of them passed, some did fail. Mainly because of CRLF/LF inconsistencies, so I changed those the test data to use LF. It is also a warning that this tool only works with platform "newline" - CRLF in Windows, and LF in Linux - so if files were to be exchanged between platforms, they must be properly translated first before use.
Here are the individual patches.
- regex patch
- exec patch
- test-case patch
They apply on top of the commit 93804d4 from 2015-02, which was the latest when I wrote this. They are licensed in the same way as the original CSVfix is licensed.
If CSVfix is not powerful enough for you, there are other similar tools:
1. miller is a tool in very similar spirit with CSVfix, but it is (much) more sophisticated. Its "data transformation language" looks more expressive than the one in CSVfix. If you have a problem you cannot solve with CSVfix, miller will probably help you. As a bonus, it is still in active development - that means bugs will be squashed. It is written in C, you will need to compile it if it is not in your package repository. (Fatdog, naturally, has it in its repository).
2. csvkit is a collection of tools that more or less perform the same functions as CSVfix. It supports direct conversion to/from Excel files, importing/exporting into databases (sqlite and postgresql as documented, perhaps others too), as well as running direct SQL queries from CSV files (and databases too). It is written in Python3 so you can install it using pip3. Fatdog has this in its repository too (so you can install it using package manager instead of pip3).
Comments - Edit - Delete
Release Notes and Forum announcements
Get it from the usual locations:
Primary site - ibiblio.org (US)
nluug.nl - European mirror
aarnet.edu - Australian mirror
uoc.gr - European mirror
ISO Builder: Get it from here: http://distro.ibiblio.org/fatdog/iso/builder/ and choose the builder dated 2019.05 and the package list for 801.
Comments - Edit - Delete
It has not been a smooth ride all along. Living in the "bleeding edge" means that you really need to prepare to bleed (that's why we don't update the base on every release - it would be downright impossible). Latest packages don't always build, and when they do, they don't always run, and they do, they don't always run stably, and when they do, they don't always work, and when they do, they don't always work correctly, and when they do, they don't always provide good performance, and so on, and so on - you get the picture.
But we have finally arrived. It may not be perfect, and it never will, but for us - it is good enough for day-to-day usage; so the decision to release.
This blog post documents a few of the stumbling blocks that we passed through on our way to the Alpha release. By sharing the knowledge, I hope that others on the same journey can avoid them.
Warning: the information that comes after this is going to be very technical. Don't worry if you don't understand it - just use whatever that you do.
The particular bug that took as considerable time (weeks) to solve was this: it's a bug that causes the desktop to unpredictable, involutary exit to the console.
And it turns out, this problem has __multiple__ underlying causes. Each cause ends up with the X server exiting (sometimes gracefully and sometimes not) so that we're dropped back the console.
Sometimes there crash messages in Xorg.0.log, sometimes don't. Sometimes the exit is immediate (X goes down and we're back in the console), sometimes it's gradual (applications start to fail one by one, before X itself finally gives up its ghost and dies).
Bug #1: fontconfig doesn't like its cache to be tampered with.
This bug happens only when running with the RAM layer (savefile=ram:device:xxx, in Puppy's parlance this is pupmode=13). When anything that uses fontconfig starts (e.g X, gtk2, etc), fontconfig will be initialised and its first action is to scan all the font directories and makes its cache.
When we run using the RAM layer, these caches are stored in the RAM layer, and eventually will be "merged-down" to the actual savelayer (copying the files from the RAM layer to the savelayer, and then removing the copy on the RAM layer, and then refreshing the aufs layered filesystem so that the copy on the RAM layer gets re-surfaced on the root of the filesystem).
This has worked for the longest time, but we found out that in Fatdog 800 this isn't the case. Even the process of copying the files from RAM layer to savelayer (not even deleting them) triggered a cascade of failure in fontconfig, which eventually resulted a crash in all higher-level libraries and applications that uses this.
Fixes #1: We still don't really know what changed - this could be a change in the kernel, fontconfig itself, glibc, or others (remember, in 800, with a new base, **all things were updated** so we can't easily isolate one component from another), but once we know what triggered the collapse, we worked around it by making sure that fontconfig caches are not touched during the merging process.
Bug #2: Xorg server crash on radeon-based systems when DRI3 and glamor is enabled (the default settings).
This has been a long running bug due to Mesa (open-source OpenGL 3D library) changing its infrastructure to support newer, more powerful radeon cards, changing both the acceleration API (DRI2 to DRI3), acceleration methods (EXA to glamor), memory management (GEM, GBM, etc).
But the bug isn't in Mesa alone. Eventually Mesa needs to interface with the video driver, so co-operation with xf86-video-ati driver is needed.
And then there is the kernel too, the radeon DRM driver from the kernel.
There are multiple components and every component is a potential source of failure (which in this case they all contributed to the problem one way or another).
To make it worse, the problem is completely unpredictable. The system can run hours without a glitch before the desktop crashed, or it can crash in next hour after booting. It brought a completely un-reliable experience.
There is no good solution for this because every component keeps changing, so updating one component could very well break another. All we can do is watch bugzillas, forums, mailing lists, and listen to possible solutions.
Fixes #2: I think in this case, we got lucky. Most of the bugs were fixed in mesa 18.2.3, and the final bug was fixed in xf86-video-ati git-master, one commit after 18.1.0. We're going to stick with this combination for a while!
Bug #3: After an unpredictable amount of time, Xorg server will crash (due to failed assert), giving up messages similar to this:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
pidgin: xcb_io.c:259: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
There is one unanswered report here: https://bugzilla.redhat.com/show_bug.cgi?id=1582478
This initially happened on ROX-Filer when it was worked heavily, so naturally we thought the problem was with ROX-Filer. But then it started to happen elsewhere (other GTK applications), so it could be anywhere in gtk2, glib, glibc, aufs kernel module, or even the kernel itself.
We scoured for solutions for similar problems, and we got some solution like this: https://forum.freecadweb.org/viewtopic.php?t=28054
But they don't work and they don't make sense. FreeCAD is a 3D-heavy application, so disabling DRI3 and (in some others links, disabling 3D hardware-acceleration) doesn't make sense for applications like ROX-Filer which is purely 2D and doesn't make use of any acceleration at all.
This was especially difficult to pinpoint because it happened randomly; and it was one of the thing I would have filed into "unsolved" files, were it not for SFR. SFR found a way to reproduce this problem reliably (by clicking the "refresh" button on ROX-Filer a few hundred times - and he even provided a automation script so we don't have to buy a new mouse after every experiment ).
Once we can reproduce this, re-building the libraries with debug symbols and running them under "gdb" quickly pointed out that the problem is within libxcb - a library at the bottom of the Xorg stack.
Bisecting on libxcb, we found that the problem is caused by a particular code commit that tries to "fix" another bug when dealing with Vulkan drivers:
But the way it was fix is, in my opinion, is incorrect (it was reading stuff when it shouldn't - this kind of thing should be protected with a mutex or we'll end up with a race).
Fixes #3: So we reverted this commit and poof! - the problem disappears. I tested clicking the button to about 16,000 times and no more crash.
This was the last bug we squashed.
So there. One symptom, three underlying problems, that can be triggered at different semi-random times, resulting in a totally different error messages and behaviour, confusing all of us.
We falsely declared victory after the first and the second were squashed - only to be humiliated when the crash happened again, in a slightly different way. By the time we squashed the last bug, we were wary enough __not__ to declare it fixed until a few days later and it was finally confirmed that we've finally made it through.
All in all, we spent more than a month to solve all of them. Now that we've past through them, I hope others can avoid the same mistake.
Meanwhile, enjoy Fatdog64 800 Alpha!
Forum announcement here: http://www.murga-linux.com/puppy/viewtopic.php?t=114719
Release Notes here: http://distro.ibiblio.org/fatdog/web/800a.html
Comments - Edit - Delete
Today has been an exciting day for Fatdog64. For me at least, Fatdog64 800 has now entered the "eat own dogfood" phase. I have migrated my build machine to Fatdog64 800. In another word, Fatdog64 800 is now self-hosting. This is the the phase that we have always done since the early days of Fatdog - we use it ourselves first, internally, for actual day-to-day purposes, to make sure we weed out the most obvious and most annoying bugs. We suffer these bugs so you don't have to. Of course, some would still slip out; and that's why more testers means lesser bugs; and fortunately, there are now four of us in the Fatdog team, and we have helps from other pre-release testers too. We'll stay in this phase for as long as it is needed to polish it up.
It has been a long and winding road to get to this. For those people who aren't involved, they probably aren't aware of the effort that goes to a project like this. Some people says, a distro is just a collection of stuff, right, and you don't write that stuff - you just package them. What's so hard about it? To that, I could have replied "well if you think it's so easy then why don't you do it yourself" - but instead, I'd choose to explain what happens behind the scenes. Along the way, I can explain some key decisions that makes Fatdog what it is today.
Okay, so a distro is just a collection of "packages". That's correct, in general, but as in everything, the devil is in the details. First and foremost: where do these "packages" come from? You've two choices here: build your own, or use someone else's. If you use someone else's packages, then your distro effectively is a "derivative", even if you call it that way or not.
We don't want Fatdog to become a derivative, at least, not Fatdog64 (I have another stagnant project called Fatdog-Like which *is* a Fatdog derived from a parent distro - but it's not going anywhere at the moment due to lack of time and interest), and the reason is not because we simply don't like to be called as "derivative".
The reason is deeper: it's about management and control. Using someone else's packages means you don't have full-control over the decisions that goes into the making of that packages - from the simple things like "which version is available", to more complex things like what is the optional libraries linked to it (this determines overall size and functionality); where is the configuration data stored; what is the build-time configuration parameters, etc.
Okay, so we don't want to be derivative.
We want to strike it on our own. What's next?
Well, what's next is we need to build our own packages then. Before we build our own packages, there are a few things that we need to sort out. Firstly, the compiler. A compiler is special, because, a part of the compiler is always attached to the final program (=the run-time). If you use an existing compiler, whoever made that compiler already made a decision for you (at the very least - the version of the compiler), which will get carried on to all of your packages --- even if all those other packages are built by you. So, no, we cannot use an existing compiler, can we? We have to build our own compiler ourselves (more popularly known as the "toolchain" because a compiler is just one of the components that you need to build a program from source - there are also the linker, the libc, and others. I'd gloss over the problems that a correct functioning toolchain requires very specific combination of correct versions of its components).
Well, how to build a compiler then? It just another package, right? No. The compiler we build is special - the program it will build is not meant to run in the machine that the compiler is run; instead, that program is supposed to run in our brand new distro, which currently exists in the gleam of our eyes only. Building a compiler like this is what you call as "toolchain bootstrapping" (aka chicken-and-egg problem); and the compiler you produce this way is a cross-compiler. I'm not going to explain terms like this here - I will assume that if you're interested enough to read this, you have enough motivation to google for terms that you don't understand.
Ok, you've googled it - and as it turns out there are tons of tools to build a cross-compiler! There is "buildroot" from busybox team, and there is "crosstool-ng", and there are many others! Problem solved, no? Eh, the answer is still no. Most of these tools produce a cross-compiler all right, and they do it very beautifully. Only one problem - most of these tools are NOT capable of building a cross-compiler which can build a native compiler (that is, a compiler that will eventually run in the target system). Which means that we will forever be dependent on them to build packages for us. That is not good. We need a cross-compiler that can eventually build a native compiler so that we can use native compiler to build the rest of the packages.
Actually, any good cross-compiler can be used to build a native compiler. You just need to know how. And it's not easy. Even the process of building a corss-compiler itself is almost black magic - that's the reason why there are numerous tools that help you to do it. Fortunately, there is one project that aims to decipher all these gobbledy-gook into something that you can understand. That project guides you, step by step, through the process of making a cross-compiler, and how to build a native compiler. That project is the Linux From Scratch project (LFS). It is not a tool, it will not build a compiler for you, but it is a book, a guide, that will instruct you exactly how to do it, step by step, while explaining why certain things must be done in a certain way.
Fatdog64, since version 700, is based on LFS.
Once we've got the compiler, then we need to build the packages using it. The LFS is extremely helpful, it will guide you to build minimal set of packages that will enable you to build a minimal system that can boot to a console, in a bash shell. And that's when LFS ends. You end up with about 50 packages gives or take including the toolchain. But at least your target distro is now alive, with a native compiler in it that you configure it yourself (the LFS instructions are just a "guide", and you're welcome to vary it for your own needs once you know exactly what you're doing - so what you build is effectively your own compiler, not LFS'), that you can use for building the rest of the packages.
Ok. The rest of the packages. Where would they come from? Let say, ummm, you want to build a web browser. Firefox sounds good. Okay. How do build a Firefox web browser from scratch? Go to Mozilla website, spend a couple of hours digging in and out ... oh, I need to build a "desktop" first before I can even begin to build Firefox. And even with the desktop, there are these "libraries" that I need to have in order to build it. I also need tools - and certain tools must be very specific version (e.g. autoconf must be version 2.13 exactly and nothing older or newer). But how to build a "desktop"? A desktop is system of many components - quickly broken down to window managers, panel manager, file manager, system settings ... and then the basic graphics subsystem, of which you can choose between X desktop and Wayland as of today. X is more popular, so you decide to explore it - then you have X libraries, XCB libraries, input drivers, video drivers, and servers. And all those things needs supporting libraries before you can even build them - they need gzip libraries, XML libraries, etc down the rabbit hole we go. So how do we even start?
Well, within the umbrella of the LFS project (but run by different people), there is this project called BLFS - Beyond LFS. Its purpose is, you guess, to provide details about building packages which aren't part of LFS. For every package that it describes, it tells you: (a) where to get the source files, (b) what are the dependencies for that package (=what packages must be built and installed before you can build this one), (c) the commands to build it properly. BLFS is much larger in scope than LFS but even it does not cover everything. It will get going, though, as it says at the top of the book: "This book follows on from the Linux From Scratch book. It introduces and guides the reader through additions to the system including networking, graphical interfaces, sound support, and printer and scanner support." So it does get you going in the right direction. It even tells you how to build Firefox, and what exactly you need to build before you can do it (you're still going down the rabbit hole, but at least somebody holding a ladder so you can always climb back up).
Fatdog64, since version 700, uses parts of BLFS as the source of some of its packages.
But there is on major problem here. Both LFS and BLFS shows and guides you to build an operating system for yourself. It's like building a one-person distro. You cannot easily copy the resulting system into a distribution media, not without tainting it with your own personal information and machine-specific configurations. (the keyword is here "easily" - with enough effort surely you can do it - obviously WE are doing it for Fatdog64). No matter, you say. I'm just building a distro for one, for myself. So all is good, right? No. With the LFS (and BLFS), it is easy to add new packages into the system, but it is rather difficult to get rid of an installed package. All packages are installed to the target system as they're built, without any records of which files goes where; so it's difficult or even impossible to remove without breaking the system.
The ability to track installed packages, and thus remove them (in addition to installing one) is collectively known as "package management". Any decent distro has one. Package Management is not included in LFS/BLFS because it "gets in the way" of explaining how things works - which its main objective. It only goes as far as saying that a package management IS needed, and there are many possible ways to do it. Look it at LFS Chapter 6.3 if you're interested.
So, you need a package management. A package management has two parts - the "creator" that enables you to build a "bundled" package, and the package management proper that can install/uninstall/view installation of your "bundled" packages. The "creator" part must be used in conjunction with your build process; because it needs to keep track of the files produced by your build, collect all those files, and bundle them up in package.
Easy, you say. Just google it up, and you will find "porg". Or you can even use existing package management system. After all, many distros share the same system; it is unnecessary to invent a new package management system (yes, proper and correct package management system is HARD). Why don't I just take Debian's package management system (dpkg), or RedHat's one (rpm), or Slackware's one (tarball), or many other myriads ways that have been suggested?
Well yes we can.
From version 700 onwards, Fatdog64 uses Slackware's package management system ("pkgtools"), fortified with slapt-get from jaos.org, modified for our use.
"pkgtools" is choosen because it's easy to create its packages, it's easy to host and publish the packages, it has tools that can extend it to support remote package management and dependency tracking (slapt-get), and the packages are basically tarballs that - in the worst case - you can always "untar" to install without needing special tools. No other package management tools comes even close.
Okay, once you choose a system then you need to hook it up with your build system so that the "creation" part of the package works, as I said above. I'd gloss over this fact and assume you can already do it. Let's move on.
Hang on, you said. We already bootstrap a system, have enough guides to build everything up to a web-browers and multimedia player (vlc), can install and uninstall packages, so what's next?
Ok, what's next? How about package updates. Software is being updated. What's new yesterday is old today and obsolete tomorrow. You need to keep building packages. These updates are not in the LFS/BLFS books, because they're published semi-annually. In between, if there is any updates, you must roll on your own sleeves and figure out how to do it yourself (it shouldn't be too hard now if you can follow BLFS guides this far). Ok, so updating is easy. *IF* you do this everyday. But if you don't - well, do you still remember how you built the previous version of the package? Do you remember the build-time flags you specified 3 months ago? Welcome to the club - you're not the only one.
You first response to the question is - I will make sure I keep a note of all the configurations, library dependencies, etc etc when I build the packages. Or, perhaps, even simpler, I will just stick to LFS/BLFS update cycles, so no need to write my own notes. I'm not that desperate to live in the bleeding edge anyway.
OK. If you decide to stick to BLFS, I have nothing else to say, but if you said you'd want to keep notes, then allow me to go a bit further. Rather than making a note, which you need to "translate" into your action when build the package, why don't you write them in the "scripting" language? So next time you can tell the computer to "read" your script for you and do the build too. Sound nice and too good to be true? It isn't, and it is actually the perfect solution. With a "build script", not only you know remember how to build a package, you also save time and (with exceptions) you have accomplished a "repeatable build" - which means that you can repeat the build many times and get a consistent result.
After a while, not only you want to record the build process, you may as well keep a record the location of the source package, perform the download, identify that the downloaded source package is correct (using checksum) before actually building it. You may even want to keep information about library dependencies there.
And if you're like me, after a while you will start to notice two things. (1) About half the content of the script is identical. It's always wget (or curl), then md5sum (or sha512sum), then extract, then apply patches, and build, then activate package-management-creator hooks, and then install and make package. The (2) point that you notice is that with the proliferation of build scripts, you need to manage them, and have the computer build them in the correct order (instead of you manually sorting out the build order).
Congratulations. You have recognised the need for a distro build infrastructure (shortened as "build system"). What we have been calling as "build scripts" are usually known as "build recipes"; once we take out the "scripting" out of them and move them into shared build infrastructure. Some people consider build infrastructure part of package management (because they can be very closely coupled) but they're actually separate systems.
Most major distros have their own distro build system, for example, Debian has "debuild", RedHat has "rpm", Arch Linux has "PKGBUILD", Slackware has SlackBuilds (for 3rd party packages only), etc. Each of these build systems have their own way to specify the "recipes" - some highly structured like debuild and rpm, some are rather loose like Arch PKGBUILD. You can use them, you don't have to re-invent the wheel. Of course, you can also come with your own if you wish.
Fatdog64 uses its own home-brewed build system conveniently named "Fatdog pkgbuild" (no relation to Arch Linux build system of the same name).
Simply because we found that none of the existing build systems have the features that we need (mainly simple enough to be understood and written but flexible enough to build complex packages). Fatdog64 build's system is more loosely defined (similar in spirit to Arch Linux) as opposed to the highly structured build system like rpm or debuild. It has proven itself enough to be able to build a customised firefox and libreoffice in a single-pass.
Ok. You have now gone a long way from building packages by hand manually and installing directly (./configure && make && make install). You are now the proud owner of a build system that can (re-)build the whole system in one command call. With some clever scripting you can even make install these packages into a chroot, and create an ISO file ready for distribution. Your job is done, you're now official an distro builder! Congratulations!
But wait. I don't have to go through all these processes. There are already "distro build system" out there, complete with fully populated recipes for every software under the sun and the moon! There is one called T2-SDE, for example. "buildroot" from busybox can actually build an entire distro's worth of packages by itself, all nicely packaged into tarballs too. Or you can start with debootstrap from Debian and start working your way up - Debian publishes every single one of their recipes, from every version ever released. And wait, they're not the only one. You have openwrt, you have ptx-dist, you have open-embedded, you have gentoo, you have yocto, and many others that I've forgotten. (You can even include android in the list - yes AOSP is a distro build system). Why not just use them?
Well, why not. If you like them, then by all means use them. Just remember this: every single build system released out there, is released to serve a purpose. Investigate that purpose is, and see if it is aligned with what you want to do. Also, all those build system (and recipes) are maintained by others, and they follow different objectives and schedules than you. This may or may not be important for you.
Fatdog64 500 and Fatdog64 600 were originally build using T2-SDE. T2-SDE was the build system used to build packages for earlier Puppy Linux builds too (version 4.x - the Dingo series). The reason why we drop T2-SDE is again because of management and control. Having T2-SDE is great because we don't have to bother about recipes and upgrades anymore, someone else is taking care of that for us. But it also means that version updates etc depends on the maintainer. Adding new packages (new recipes) depends on the maintainer. Etc. We can of course update the recipes on our own (once we understand the format), but then it means we to start keeping track of these recipes ourselves. The more we have to change, the more we have to maintain ourselves. Some packages' changes only affect themselves, some affect others (e.g. library updates more often than not introduces incompatibilities, which means that all packages that uses this updated library will now also have to be updated themselves, causing an avalanche of recipe updates), so before you know it, you basically have "forked" your build system from the original maintainer. This is even more true if you find "bugs" in the build system which the maintainer won't fix for whatever reasons, and you ends up fixing it yourself. Congratulations, you're now maintaining a distro build system that you don't fully understand and was created by someone else for objectives that may or may not align with yours.
So, okay, you decide to start a build system on your own. At least, this is your system, you know it upside down and you can debug it with your eyes closed. You write this exactly to your own needs - nothing less, nothing more. Then you start to populate this system with recipes.
You can initially source the recipes from BLFS, and then you can start writing your own, or even use recipes from Debian, RedHat, OpenSuse, Arch, or wherever else you can find them. Lots of time spent in experimenting to make sure that the right combination of packages and libraries all work well together and produce the best outcome that you want (in terms of feature, performance/speed and size). If you use only one source (e.g. BLFS) this is not important - the tuning is already done for you. But if you mix recipes from many sources, they have have assumptions that is no longer true when you apply them in your system (e.g. assuming a library is installed when it is not, etc); you will find out when you get a build failure (or worse: a run-time failure) so you have to tinker and adjust. Imagine, then: at the very near end of the building, you've got a compilation failure. You've got to troubleshoot this, figure out why it fails, what's the probably fix, and try to build again. And it fails again. So you investigate again, and try fixing up again. And then rebuild. This cycle continues until you finally get a working recipe that builds correctly, or until you give up. But if this is a very important library which is used by many other packages, "giving up" is not an option (unless you want to give up building the distro altogether). Now imagine this trial-and-error cycles, for a large package like libreoffice which can easily take a few hours to build. A single, big, and yet important recalcitrant package can easily delay progress by days.
Of course you're not always on your own. I don't want to make it sound more difficult than what it is. stackoverflow.com is here to help. You can also ask linuxquestions.org or similar places, and if you're lucky, you're not the first one to encounter the problem, so google is your friend. But once a while you do get unlucky and the problem you need to solve is truly yours only.
Anyway, let's move on. After spending countless, sleepless and thankless hours building your distro, finally come to the period of testing (which is where we are at, now, for Fatdog64 800). This is where the proof meets the pudding - see if those recipes get us a good cake. And then only way to know whether the food is good is to eat it, so the mantra "eat your own dog food". After an eternity of testing, you finally come to the conclusion that you're going to have to publish this distro or it will be obsolete before it is released.
Congratulations! It's release time! (We're not there yet for Fatdog64 800 - but we have been through this many times with earlier versions - you can refer to all our previous releases in Fatdog History site). To be on the safe side, you don't immediately claim for the Final release (aka "Gold" release), but you call is a "test" release and call it using Greek alphabet to make it cooler (alpha release, beta release etc - but normally it stops at beta because "gamma" sounds very bad for your health - after all gamma radiation is what turns Bruce Banner into Hulk, remember?).
And then the silence is deafening. Nobody (in their right mind) will touch a test release within a 10-feet pole (unless they're dedicated testers, and thankfully, over the years we have managed to attract some of them - so the silence is not usually deafening for Fatdog release. But others don't fare as well). Oh well, after a few weeks of test release, we think we've squashed all the bugs we can find (and willing to, and able to fix). It is now finally the time for the Grand release, aka Final, the Gold.
Drum rolls please!
As soon as we made the final announcement, comes the news that the kernel we included in the final release has a severe CVE problem (privilege escalation). Or that the openssl version that we use has CVE reports about remote exploits. Or the install scripts corrupts the user's hard disk. Or there is yet one more bug that we missed earlier in the test release. This is not including people whose only sorry life's existence depends on trolling people (Again: this paragraph, like the the rest of this post, is illustration only. We don't usually get it so bad - in fact we've evaded the worst and fared quite well in our releases so far). So what can you do? Depending on the severity of the problem, you can: (a) ignore it, or (b) fix it and issue a minor version update, or (c) pull out the release completely until you can work the problem out. Oh, and just ignore the trolls.
But the life of a distro doesn't end here, unless you're fine doing just doing one-trick pony. Software gets updated, bugs got found, more CVEs got reported, so you've got to update your releases too. Sounds familiar isn't it. But you've got your build system! You've got your recipes! So no problem, right?
You update your recipes, (re-)build them in your build system, spending more countless hours fixing breakage caused by the updated recipes, etc. And then you issue an update - this can be package update, or build a new ISO and issue a minor revision release, etc. Generally it's quite manageable unless you're trying to "live in the edge" and wants to always be on the latest version on everything (note of warning: bleeding edge is not wise. Newer versions comes with fixes but also comes with new bugs too).
But updates doesn't last forever. There are components of the system that you can't update. "libc" for example. It is part of the toolchain. It is part of every software in your distro. To update it, firstly you need build a new toolchain. Secondly it means either (1) you need to rebuild all the packages with the new toolchain - this is the proper way of doing it, or (2) just drop the old libc and put in a new one - this is the improper way of doing it and has great risks of introducing unpredictable crashes. In other words, unreliablity.
So, eventually, you have to do the proper way (1) above. This is what in Fatdog64 parlance is what we call as "updating the base". It is what comprises a major release, in Fatdogs. All minor version updates have the same base - same compiler, same libc. For example 600, 601, 602, 610, 611, 620, 621, 630, 631 releases all use the same toolchain and same toolchain libraries. When we move to 700 series, we have a new toolchain - "the base". Fatdog64 800 is one such major release - we're moving from gcc 4.8.3 and glibc 2.19 in 710 series to gcc 7.3.0 and glibc 2.27 in Fatdog64 800.
Naturally, when we have to rebuild all of the packages, we may as well update them as we go. So, not only we're updating the toolchain, but we're updating every single one of the packages that we have build previously. The fact that we've sourced some of our packages from LFS and BLFS doesn't help - we still have to review and update (all of) our recipes; and we still have to build it. Again, we while we borrow and use recipes from many sources (including writing our own as needed), the environment and the combination of packages that we build and use is completely unique to us, so basically we have to repeat the countless, sleepless, and thankless hours of tuning the updated recipes (=all of them) again and again, waiting for a package to build just to see the compiler spits out cryptic error messages because (a) new gcc now uses new c++ standards which considers previously accepted language construct as an error unless you know certain magic incantations that will bring its understanding of "ancient wisdom" back - but sometimes even such incantation doesn't work as advertised and you need to patch it (b) openssl has a new ABI that makes all other openssl-using packages to fail and must be patched (c) poppler changes some of the method signature for no good reason and causes undecipherable error messages to some, but not all, packages that uses it, (=me spending hours convincing scribus to build) or (d) Qt goes yet again for another re-factoring spree that breaks all except the latest of the software; whose fix is easy just insert #include <QStyle> but of course you must know that this is the solution (and on which file you need to insert it) (e) original website goes dead, need to confirm if this is the latest/final version of the software or if anyone picks up the debris and start a fork (f) change of source code hosting - we have been in the business long enough to see migrations sourceforge to googlecode to github and now to gitlab with pieces left along the way - so we need to confirm which hosting contains the latest (g) and many other fine gotchas in similar vein.
So. Having a build system makes maintenance oh so much easier. But when it comes to major updates like this, there is always serious work involved behind it. It is almost like re-starting everything from scratch again (because it actually is). Fatdog64 is relatively small, we have only about 1500 packages (not including the contributed packages), but even this takes considerable amount of time to maintain and especially to perform major update. To give you an idea, Fatdog64 800 work was seriously started not long after LFS 8.2 is released, in March (our based is based on LFS 8.2 - we started ours major cycle update around late May). At the time of this writing, LFS 8.3 has been been released, and we're still in internal testing phase.
Oh, one more thing. Even though we use LFS as the base, it is not purely LFS. LFS is not multi-lib aware. As early as Fatdog64 700 (which uses LFS 7.5), we've tried to build it in away that is 64-bit clean - that is, all 64-bit libs goes for "lib64". This we can tack on 32-bit compatibily libraries in "lib", using libraries we took from other 32-bit distros (mainly from Puppy Linux variants). In Fatdog64 710 we upped the ante and build a full multilib version - which means that both the build system now builds both 64-bit and 32-bit packages directly. One of the key parameter of success is the ability to build wine - which requires both 64-bit and 32-bit infrastucture to work. LFS is not multilib aware, does not support multilib, and does not plan to do it, because, doing so, will just obscure the points (same reason why package management is not included). And I fully agree.
To that end, in 710 our base was actually shifted to CLFS 3.0.0. CLFS - Cross-LFS is an extension of CLFS that builds Linux distros for target platform which is not identical to the original host platform (LFS requires that host and target platform to be the same - if you start on 32-bit system, you end up with 32-bit distro), and in addition, it supports multilib too. But in term of the age of the packages, CLFS 3.0.0 was very close to LFS 7.5 so that they're virtually identical (same glibc versions, gcc only differs in revision numbers, etc) so aside from the build infrastructure changes, CLFS-based Fatdog64 710 is identical to LFS-based Fatdog64 700.
The point is, we don't just take and use LFS/BLFS recipes (or any other 3rd party recipes) verbatim. We need to convert them into multilib-compatible recipes, we need to create the 32-bit version of the recipes, and lastly we need to test them that they build, and that they work. There is serious amount of work going behind the scenes that people rarely see.
And lastly - all those packages you build, you need to publish it somewhere, right? Debian users uses apt-get to install new packages. RedHat/Centos uses "yum". Arch uses pacman. What will your distro use? Where will you publish the packages? How to maintain and ensure that this "software repository" / "package repository" ("repo" for short) of yours is up-to-date? If you have a non-traditional delivery system like Fatdog64, whose entire operating system files are kept in the "initrd", how can you deliver updates? These are important non-rhetorical questions which I leave as an exercise for the reader.
So, do you still want to start and maintain your own "personal" distro?
Sure, writing and programming a software as complex as libreoffice is difficult and hard, especially always playing catch up to moving goalpost of "MS compatibility". Sure, writing and programming a web browser as complex as Chromium is hard - especially playing catch up to the "Living Standard". But building and maintaining a distro with over 1000 independent moving components created by different groups of people who may or may not be aware of each other is not exactly a walk in the park either.
It's fun, though. If you just have the right mindset. Which is why I'm still here, and will still be here for foreseeable future, ceteris paribus.
Comments - Edit - Delete