| <html><head><title>toybox FAQ</title> |
| <!--#include file="header.html" --> |
| |
| <h1>Frequently Asked Questions</h1> |
| |
| <h2>General Questions</h2> |
| |
| <ul> |
| <li><h2><a href="#why_toybox">Why toybox? (What was wrong with busybox?)</a></h2></li> |
| <li><h2><a href="#capitalize">Do you capitalize toybox?</a></h2></li> |
| <li><h2><a href="#support_horizon">Why a 7 year support horizon?</a></h2></li> |
| <li><h2><a href="#releases">Why time based releases?</a></h2></li> |
| <li><h2><a href="#code">Where do I start understanding the toybox source code?</a></h2></li> |
| <li><h2><a href="#when">When were historical toybox versions released?</a></h2></li> |
| <li><h2><a href="#bugs">Where do I report bugs?</a></h2></li> |
| <li><h2><a href="#b_links">What are those /b/number links in the git log?</a></h2></li> |
| <li><h2><a href="#opensource">What is the relationship between toybox and android?</a></h2></li> |
| <li><h2><a href="#backporting">Will you backport fixes to old versions?</a></h2></li> |
| <li><h2><a href="#dotslash">What's this ./ on the front of commands in your examples?</a></h2></li> |
| |
| </ul> |
| |
| <h2>Using toybox</h2> |
| |
| <ul> |
| <!-- get binaries --> |
| <li><h2><a href="#install">How do I install toybox?</h2></li> |
| <li><h2><a href="#cross">How do I cross compile toybox?</h2></li> |
| <li><h2><a href="#system">What part of Linux/Android does toybox provide?</h2></li> |
| <li><h2><a href="#mkroot">How do I build a working Linux system with toybox?</a></h2></li> |
| </ul> |
| |
| <hr /><h2><a name="why_toybox" />Q: "Why is there toybox? What was wrong with busybox?"</h2> |
| |
| <p>A: Toybox started back in 2006 when I (Rob Landley) |
| <a href=https://lwn.net/Articles/202106/>handed off BusyBox maintainership</a> |
| and <a href=http://landley.net/notes-2006.html#28-09-2006>started over from |
| scratch</a> on a new codebase after a |
| <a href=http://lists.busybox.net/pipermail/busybox/2006-September/058617.html>protracted licensing argument</a> took all the fun out of working on BusyBox.</p> |
| |
| <p>Toybox was just a personal project until it got |
| <a href=http://landley.net/notes-2011.html#13-11-2011>relaunched</a> |
| in November 2011 with a new goal to make Android |
| <a href=http://landley.net/aboriginal/about.html#selfhost>self-hosting</a>. |
| This involved me relicensing my own |
| code, which made people who had never used or participated in the project |
| <a href=https://lwn.net/Articles/478308/>loudly angry</a>. The switch came |
| after a lot of thinking <a href=http://landley.net/talks/ohio-2013.txt>about |
| licenses</a> and <a href=http://landley.net/notes-2011.html#21-03-2011>the |
| transition to smartphones</a>, which led to a |
| <a href=https://www.youtube.com/watch?v=SGmtP5Lg_t0>2013 talk</a> laying |
| out a |
| <a href=http://landley.net/talks/celf-2013.txt>strategy</a> |
| to make Android self-hosting using toybox. This helped |
| <a href=https://code.google.com/p/android/issues/detail?id=76861>bring |
| it to Android's attention</a>, and they |
| <a href=https://lwn.net/Articles/629362/>merged it</a> into Android M.</p> |
| |
| <p>The unfixable problem with busybox was licensing: BusyBox predates Android |
| by almost a decade, but Android still doesn't ship with it because GPLv3 came |
| out around the same time Android did and caused many people to throw |
| out the GPLv2 baby with the GPLv3 bathwater. |
| Android <a href=https://source.android.com/source/licenses.html>explicitly |
| discourages</a> use of GPL and LGPL licenses in its products, and has gradually |
| reimplemented historical GPL components (such as its bluetooth stack) under the |
| Apache license. Apple's |
| <a href=http://meta.ath0.com/2012/02/05/apples-great-gpl-purge/>less subtle</a> response was to freeze xcode at the last GPLv2 releases |
| (GCC 4.2.1 with binutils 2.17) for over 5 years while sponsoring the |
| development of new projects (clang/llvm/lld) to replace them, |
| implementing a |
| <a href=https://www.osnews.com/story/24572/apple-ditches-samba-in-favour-of-homegrown-replacement/>new SMB server</a> from scratch to |
| <a href=https://archive.org/details/copyleftconf2020-allison>replace samba</a>, |
| switching <a href=https://www.theverge.com/2019/6/4/18651872/apple-macos-catalina-zsh-bash-shell-replacement-features>bash with zsh</a>, and so on. |
| Toybox itself exists because somebody with in a legacy position |
| just wouldn't shut up about GPLv3, otherwise I would probably |
| still happily be maintaining BusyBox. (For more on how I wound |
| up working on busybox in the first place, |
| <a href=http://landley.net/aboriginal/history.html>see here</a>.)</p> |
| |
| <hr /><h2><a name="capitalize" />Q: Do you capitalize toybox?</h2> |
| |
| <p>A: Only at the start of a sentence. The command name is all lower case so |
| it seems silly to capitalize the project name, but not capitalizing the |
| start of sentences is awkward, so... compromise. (It is _not_ "ToyBox".)</p> |
| |
| <hr /><h2><a name="support_horizon">Q: Why a 7 year support horizon?</a></h2> |
| |
| <p>A: Our <a href=http://lists.busybox.net/pipermail/busybox/2006-September/058440.html>longstanding rule of thumb</a> is to try to run and build on |
| hardware and distributions released up to 7 years ago, and feel ok dropping |
| support for stuff older than that. (This is a little longer than Ubuntu's |
| Long Term Support, but not by much.)</p> |
| |
| <p>My original theory was "4 to 5 of the 18-month cycles of moore's law should cover |
| the vast majority of the installed base of PC hardware", loosely based on some |
| research I did <a href=http://www.catb.org/esr/halloween/halloween9.html#id2867629>back in 2003</a> |
| and <a href=http://catb.org/esr/writings/world-domination/world-domination-201.html#id248066>updated in 2006</a> |
| which said that low end systems were 2 iterations of moore's |
| law below the high end systems, and that another 2-3 iterations should cover |
| the useful lifetime of most systems no longer being sold but still in use and |
| potentially being upgraded to new software releases.</p> |
| |
| <p>That analysis missed <a href=http://landley.net/notes-2011.html#26-06-2011>industry |
| changes</a> in the 1990's that stretched the gap |
| from low end to high end from 2 cycles to 4 cycles, and ignored |
| <a href=https://landley.net/notes-2010.html#09-10-2010>the switch</a> from PC to smartphone cutting off the R&D air supply of the |
| laptop market. Meanwhile the Moore's Law <a href=https://en.wikipedia.org/wiki/Logistic_function>s-curve</a> started bending back down (as they |
| <a href=https://en.wikipedia.org/wiki/Diffusion_of_innovations>always do</a>) |
| back in 2000, and these days is pretty flat: the drive for faster clock |
| speeds <a href=http://www.anandtech.com/show/613>stumbled</a> |
| and <a href=http://www.pcworld.com/article/118603/article.html>died</a>, with |
| the subsequent drive to go "wide" maxing out for most applications |
| around 4x SMP with maybe 2 megabyte caches. These days the switch from exponential to |
| linear growth in hardware capabilities is |
| <a href=https://www.cnet.com/news/end-of-moores-law-its-not-just-about-physics/>common knowledge</a> and |
| <a href=http://www.acm.org/articles/people-of-acm/2016/david-patterson>widely |
| accepted</a>.</p> |
| |
| <p>But the 7 year rule of thumb stuck around anyway: if a kernel or libc |
| feature is less than 7 years old, I try to have a build-time configure test |
| for it to let the functionality cleanly drop out. I also keep old Ubuntu |
| images around in VMs to perform the occasional defconfig build there to |
| see what breaks. (I'm not perfect about this, but I accept bug reports.)</p> |
| |
| <hr /><h2><a name="releases" />Q: Why time based releases?</h2> |
| <p>A: Toybox targets quarterly releases (a similar schedule to the Linux |
| kernel) because Martin Michlmayr's excellent |
| <a href=http://www.youtube.com/watch?v=IKsQsxubuAA>talk on the |
| subject</a> was convincing. This is actually two questions, "why have |
| releases" and "why schedule them".</p> |
| |
| <p>Releases provide synchronization points where the developers certify |
| "it worked for me". Each release is a known version with predictable behavior, |
| and right or wrong at least everyone should be seeing |
| similar results so might be able to google an unexpected outcome. |
| Releases focus end-user testing on specific versions |
| where issues can be reproduced, diagnosed, and fixed. |
| Releases also force the developers to do periodic tidying, packaging, |
| documentation review, finish up partially implemented features languishing |
| in their private trees, and give regular checkpoints to measure progress.</p> |
| |
| <p>Changes accumulate over time: different feature sets, data formats, |
| control knobs... Toybox's switch from "ls -q" to "ls -b" as the default output |
| format was not-a-bug-it's-a "design improvement", but the |
| difference is academic if the change breaks somebody's script. |
| Releases give you the option to schedule upgrades as maintenance, not to rock |
| the boat just now, and use a known working release version until later.</p> |
| |
| <p>The counter-argument is that "continuous integration" |
| can be made robust with sufficient automated testing. But like the |
| <a href=https://web.archive.org/web/20131123071427/http://www.shirky.com/weblog/2013/11/healthcare-gov-and-the-gulf-between-planning-and-reality/>waterfall method</a>, this places insufficent |
| emphasis on end-user feedback and learning from real world experience. |
| Developer testing is either testing that the code does what the developers |
| expect given known inputs running in an established environment, or it's |
| regression testing against bugs previously found in the field. No plan |
| survives contact with the enemy, and technology always breaks once it |
| leaves the lab and encounters real world data and use cases in new |
| runtime and build environments.</p> |
| |
| <p>The best way to give new users a reasonable first experience is to point |
| them at specific stable versions where development quiesced and |
| extra testing occurred. There will still be teething troubles, but multiple |
| people experiencing the _same_ teething troubles can potentially |
| help each other out.</p> |
| |
| <p>Releases on a schedule are better than releases "when it's ready" for |
| the same reason a regularly scheduled bus beats one that leaves when it's |
| "full enough": the schedule lets its users make plans. Even if the bus leaves |
| empty you know when the next one arrives so missing this one isn't a disaster. |
| and starting the engine to leave doesn't provoke a last-minute rush of nearby |
| not-quite-ready passengers racing to catch it causing further delay and |
| repeated start/stop cycles as it ALMOST leaves. |
| (The video in the first paragraph goes into much greater detail.)</p> |
| |
| <hr /><h2><a name="code" />Q: Where do I start understanding the source code?</h2> |
| |
| <p>A: Toybox is written in C. There are longer writeups of the |
| <a href=design.html>design ideas</a> and a <a href=code.html>code walkthrough</a>, |
| and the <a href=about.html>about page</a> summarizes what we're trying to |
| accomplish, but here's a quick start:</p> |
| |
| <p>Toybox uses the standard three stage configure/make/install |
| <a href=code.html#building>build</a>, in this case "<b>make defconfig; |
| make; make install</b>". Type "<b>make help</b>" to |
| see available make targets.</p> |
| |
| <p><u>The configure stage</u> is copied from the Linux kernel (in the "kconfig" |
| directory), and saves your selections in the file ".config" at the top |
| level. The "<b>make defconfig</b>" target selects the |
| maximum sane configuration (enabling all the commands and features that |
| aren't unfinished, or only intended as examples, or debug code...) and is |
| probably what you want. You can use "<b>make menuconfig</b>" to manually select |
| specific commands to include, through an interactive menu (cursor up and |
| down, enter to descend into a sub-menu, space to select an entry, ? to see |
| an entry's help text, esc to exit). The menuconfig help text is the |
| same as the command's "<b>--help</b>" output.</p> |
| |
| <p><u>The "make" stage</u> creates a toybox binary (which is stripped, look in |
| generated/unstripped for the debug versions), and "<b>make install</b>" adds a bunch of |
| symlinks to toybox under the various command names. Toybox determines which |
| command to run based on the filename, or you can use the "toybox" name in which case the first |
| argument is the command to run (ala "toybox ls -l").</p> |
| |
| <p><u>You can also build |
| individual commands as standalone executables</u>, ala "make sed cat ls". |
| The "make change" target builds all of them, as in "change for a $20".</p> |
| |
| <p><u>The main() function is in main.c</u> at the top level, |
| along with setup plumbing and selecting which command to run this time. |
| The function toybox_main() in the same file implements the "toybox" |
| multiplexer command that lists and selects the other commands.</p> |
| |
| <p><u>The individual command implementations are under "toys"</u>, and are grouped |
| into categories (mostly based on which standard they come from, posix, lsb, |
| android...) The "pending" directory contains unfinished commands, and the |
| "examples" directory contains example code that aren't really useful commands. |
| Commands in those two directories |
| are _not_ selected by defconfig. (Most of the files in the pending directory |
| are third party submissions that have not yet undergone |
| <a href=cleanup.html>proper code review</a>.)</p> |
| |
| <p><u>Common infrastructure shared between commands is under "lib"</u>. Most |
| commands call lib/args.c to parse their command line arguments before calling |
| the command's own main() function, which uses the option string in |
| the command's NEWTOY() macro. This is similar to the libc function getopt(), |
| but more powerful, and is documented at the top of lib/args.c. A NULL option |
| string prevents this code from being called for that command.</p> |
| |
| <p><u>The build/install infrastructure is shell scripts under |
| "scripts"</u> (starting with scripts/make.sh and scripts/install.sh). |
| <u>These populate the "generated" directory</u> with headers |
| created from other files, which are <a href=code.html#generated>described</a> |
| in the code walkthrough. All the |
| build's temporary files live under generated, including the .o files built |
| from the .c files (in generated/obj). The "make clean" target deletes that |
| directory. ("make distclean" also deletes your .config and deletes the |
| kconfig binaries that process .config.)</p> |
| |
| <p><u>Each command's .c file contains all the information for that command</u>, so |
| adding a command to toybox means adding a single file under "toys". |
| Usually you <a href=code.html#adding>start a new command</a> by copying an |
| existing command file to a new filename |
| (toys/examples/hello.c, toys/examples/skeleton.c, toys/posix/cat.c, |
| and toys/posix/true.c have all been used for this purpose) and then replacing |
| all instances of its old name with the new name (which should match the |
| new filename), and modifying the help text, argument string, and what the |
| code does. You might have to "make distclean" before your new command |
| shows up in defconfig or menuconfig.</p> |
| |
| <p><u>The toybox test suite lives in the "tests" directory</u>, and is |
| driven by scripts/test.sh and scripts/runtest.sh. From the top |
| level you can "make tests" to test everything, or "make test_sed" to test a |
| single command's standalone version (which should behave identically, |
| but that's why we test). You can set TEST_HOST=1 to test the host version |
| instead of the toybox version (in theory they should work the same), |
| and VERBOSE=all to see diffs of the expected and actual output for all |
| failing tests. The default VERBOSE=fail stops at the first such failure.</p> |
| |
| <hr /><h2><a name="when" />Q: When were historical toybox versions released?</h2> |
| |
| <p>A: For vanilla releases, check the |
| <a href=https://github.com/landley/toybox/tags>date on the commit tag</a> |
| or <a href=https://landley.net/toybox/downloads/binaries/>the |
| example binaries</a> against the output of "toybox --version". |
| Between releases the --version |
| information is in "git describe --tags" format with "tag-count-hash" showing the |
| most recent commit tag, the number of commits since that tag, and |
| the hash of the current commit.</p> |
| |
| <p>Android makes its own releases on its own |
| <a href=https://en.wikipedia.org/wiki/Android_version_history>schedule</a> |
| using its own version tags, but lists corresponding upstream toybox release |
| versions <a href=https://android.googlesource.com/platform/system/core/+/master/shell_and_utilities/README.md>here</a>. For more detail you can look up |
| <a href=https://android.googlesource.com/platform/external/toybox/+refs>AOSP's |
| git tags</a>. (The <a href=https://source.android.com/setup/start>Android Open Source Project</a> is the "upstream" android vendors |
| start form when making their own releases. Google's phones run AOSP versions |
| verbatim, other vendors tend to take those releases as starting points to |
| modify.)</p> |
| |
| <p>If you want to find the vanilla toybox commit corresponding to an AOSP |
| toybox version, find the most recent commit in the android log that isn't from a |
| @google or @android address and search for it in the vanilla commit log. |
| (The timestamp should match but the hash will differ, |
| because each git hash includes the previous |
| git hash in the data used to generate it so all later commits have a different |
| hash if any of the tree's history differs; yes Linus Torvalds published 3 years |
| before Satoshi Nakamoto.) Once you've identified the vanilla commit's hash, |
| "git describe --tags $HASH" in the vanilla tree should give you the --version |
| info for that one.</p> |
| |
| <hr /><h2><a name="bugs" />Q: Where do I report bugs?</h2> |
| |
| <p>A: Ideally on the <a href=http://lists.landley.net/listinfo.cgi/toybox-landley.net>mailing list</a>, although <a href=mailto:rob@landley.net>emailing the |
| maintainer</a> is a popular if slightly less reliable alternative. |
| Issues submitted to <a href=https://github.com/landley/toybox>github</a> |
| are generally dealt with less promptly, but mostly get done eventually. |
| AOSP has its <a href=https://source.android.com/setup/contribute/report-bugs>own bug reporting mechanism</a> (although for toybox they usually forward them |
| to the mailing list) and Android vendors usually forward them to AOSP which |
| forwards them to the list.</p> |
| |
| <p>Note that if we can't reproduce a bug, we probably can't fix it. |
| Not only does this mean providing enough information for us to see the |
| behavior ourselves, but ideally doing so in a reasonably current version. |
| The older it is the greater the chance somebody else found and fixed it |
| already, so the more out of date the version you're reporting a bug against |
| the less effort we're going to put into reproducing the problem.</p> |
| |
| <hr /><h2><a name="b_links" />Q: What are those /b/number bug report |
| links in the git log?</h2> |
| |
| <p>A: It's a Google thing. Replace /b/$NUMBER with |
| https://issuetracker.google.com/$NUMBER to read it outside the googleplex.</p> |
| |
| <hr /><a name="opensource" /><h2>Q: What is the relationship between toybox and android?</h2> |
| |
| <p>A: The <a href=about.html>about page</a> tries to explain that, |
| and Linux Weekly News has covered toybox's history a |
| <a href=https://lwn.net/Articles/202106/>little</a> |
| <a href=https://lwn.net/Articles/478308/>over</a> |
| <a href=https://lwn.net/Articles/616272/>the</a> |
| <a href=https://lwn.net/Articles/629362/>years</a>.</p> |
| |
| <p>Toybox is a traditional open source project created and maintained |
| by hobbyist (volunteer) developers, originally for Linux but these days |
| also running on Android, BSD, and MacOS. The project started in 2006 |
| and its original author (Rob Landley) |
| continues to maintain the open source project.</p> |
| |
| <p>Android's base OS maintainer (Elliott Hughes, I.E. enh) |
| <a href=https://github.com/landley/toybox/commit/69a9f257234a>ported</a> |
| <a href=https://github.com/landley/toybox/commit/6a29bb1ebe62>toybox</a> |
| to Android in 2014, merged it into Android M (Marshmallow), and remains |
| Android's toybox maintainer. (He explained it in his own words in |
| <a href=http://androidbackstage.blogspot.com/2016/07/episode-53-adb-on-adb.html>this podcast</a>, starting either 18 or 20 minutes in depending how |
| much backstory you want.)</p> |
| |
| <p>Android's policy for toybox development is to push patches to the |
| open source project (submitting them via the mailing list) then |
| "git pull" the public tree into Android's tree. To avoid merge conflicts, Android's |
| tree doesn't change any of the existing toybox files but instead adds <a href=https://android.googlesource.com/platform/external/toybox/+/refs/heads/master/Android.bp>parallel |
| build infrastructure</a> off to one side. (Toybox uses a make wrapper around bash |
| scripts, AOSP builds with soong/ninja instead and checks in a snapshot of the |
| generated/ directory to avoid running kconfig each build). |
| Android's changes to toybox going into the open source tree first |
| and being pulled from there into Android keeps the two trees in |
| sync, and makes sure each change undergoes full open source design review |
| and discussion.</p> |
| |
| <p>Rob acknowledges Android is by far the largest userbase for the project, |
| but develops on a standard 64-bit Linux+glibc distro while building embedded |
| 32-bit big-endian nommu musl systems requiring proper data alignment for work, |
| and is not a Google employee so does not have access |
| to the Google build cluster of powerful machines capable of running the full |
| AOSP build in a reasonable amount of time. Rob is working to get android |
| building under android (the list of |
| toybox tools Android's build uses is |
| <a href=https://android.googlesource.com/platform/prebuilts/build-tools/+/refs/heads/master/path/linux-x86/>here</a>, |
| and what else it needs from its build environment is |
| <a href=https://android.googlesource.com/platform/build/soong/+/refs/heads/master/ui/build/paths/config.go>here</a>), and he hopes someday to not only make a usable development |
| environment out of it but also nudge the base OS towards a more granular |
| package management system allowing you to upgrade things like toybox without |
| a complete reinstall and reboot, plus the introduction of a "posix container" |
| within which you can not only run builds, but selinux lets you run binaries |
| you've just built). In the meantime, Rob tests static bionic |
| builds via the Android NDK when he remembers, but has limited time to work |
| on toybox because it's not his day job. (The products his company makes ship |
| toybox and they do sponsor the project's development, but it's one of many |
| responsibilities at work.)</p> |
| |
| <p>Elliott is the Android base OS maintainer, in which role he manages |
| a team of engineers. He also has limited time for toybox, both because it's one |
| of many packages he's responsible for (he maintains bionic, used to maintain |
| dalvik...) and because he allowed himself to be promoted into management |
| and thus spends less time coding than he does sitting in meetings where testers |
| talk to security people about vendor issues.</p> |
| |
| <p>Android has many other coders and security people who submit the occasional |
| toybox patch, but of the last 1000 commits at the <a href=https://github.com/landley/toybox/commit/88b34c4bd3f8>time |
| of writing</a> this FAQ entry, Elliott submitted 276 and all other google.com |
| or android.com addresses combined totaled 17. (Rob submitted 591, leaving |
| 116 from other sources, but for both Rob and Elliott there's a lot of "somebody |
| else pointed out an issue, and then we wrote a patch". A lot of patches |
| from both "Author:" lines thank someone else for the suggestion in the |
| commit comment.)</p> |
| |
| <hr /><a name="backporting" /><h2>Q: Will you backport fixes to old versions?</h2> |
| |
| <p>A: Probably not. The easiest thing to do is get your issue fixed upstream |
| in the current release, then get the newest version of the |
| project built and running in the old environment.</p> |
| |
| <p>Backporting fixes generally isn't something open source projects run by |
| volunteer developers do because the goal of the project's development community |
| is to extend and improve the project. We're happy to respond to our users' |
| needs, but if you're coming to the us for free tech support we're going |
| to ask you to upgrade to a current version before we try to diagnose your |
| problem.</p> |
| |
| <p>The volunteers are happy to fix any bugs you point out in the current |
| versions because doing so helps everybody and makes the project better. We |
| want to make the current version work for you. But diagnosing, debugging, and |
| backporting fixes to old versions doesn't help anybody but you, so isn't |
| something we do for free. The cost of volunteer tech support is using a |
| reasonably current version of the project.</p> |
| |
| <p>If you're using an old version built with an old |
| compiler on an old OS (kernel and libc), there's a fairly large chance |
| whatever problem you're |
| seeing already got fixed, and to get that fix all you have to do is upgrade |
| to a newer version. Diagnosing a problem that wasn't our bug means we spent |
| time that only helps you, without improving the project. |
| If you don't at least _try_ a current version, you're asking us for free |
| personalized tech support.</p> |
| |
| <p>Reproducing bugs in current versions also makes our job easier. |
| The further back in time |
| you are, the more work it is for us digging back in the history to figure |
| out what we hadn't done yet in your version. If spot a problem in a git |
| build pulled 3 days ago, it's obvious what changed and easy to fix or back out. |
| If you ask about the current release version 3 months after it came out, |
| we may have to think a while to remember what we did and there are a number of |
| possible culprits, but it's still tractable. If you ask about 3 year old |
| code, we have to reconstruct the history and the problem could be anything, |
| there's a lot more ground to cover and we haven't seen it in a while.</p> |
| |
| <p>As a rule of thumb, volunteers will generally answer polite questions about |
| a given version for about three years after its release before it's so old |
| we don't remember the answer off the top of our head. And if you want us to |
| put any _effort_ into tracking it down, we want you to put in a little effort |
| of your own by confirming it's still a problem with the current version |
| (I.E. we didn't fix it already). It's |
| also hard for us to fix a problem of yours if we can't reproduce it because |
| we don't have any systems running an environment that old.</p> |
| |
| <p>If you don't want to upgrade, you have the complete source code and thus |
| the ability to fix it yourself, or can hire a consultant to do it for you. If |
| you got your version from a vendor who still supports the older version, they |
| can help you. But there are limits as to what volunteers will feel obliged to |
| do for you.</p> |
| |
| <p>Commercial companies have different incentives. Your OS vendor, or |
| hardware vendor for preinstalled systems, may have their own bug reporting |
| mechanism and update channel providing backported fixes. And a paid consultant |
| will happily set up a special environment just to reproduce your problem.</p> |
| |
| <hr /><h2><a name="install" />Q: How do I install toybox?</h2> |
| |
| <p>A: |
| Multicall binaries like toybox behave differently based on the filename |
| used to call them, so if you "mv toybox ls; ./ls -l" it acts like ls. Creating |
| symlinks or hardlinks and adding them to the $PATH lets you run the |
| commands normally by name, so that's probably what you want to do.</p> |
| |
| <p>If you already have a <a href=https://landley.net/toybox/downloads/binaries/>toybox binary</a> |
| you can install a tree of command symlinks to |
| <a href=http://git.musl-libc.org/cgit/musl/tree/include/paths.h>the |
| standard path</a> |
| locations (<b>export PATH=/bin:/usr/bin:/sbin:/usr/sbin</b>) by doing:</p> |
| |
| <blockquote><p><b>for i in $(/bin/toybox --long); do ln -s /bin/toybox $i; done</b></p></blockquote> |
| |
| <p>Or you can install all the symlinks in the same directory as the toybox binary |
| (<b>export PATH="$PWD:$PATH"</b>) via:</p> |
| |
| <blockquote><p><b>for i in $(./toybox); do ln -s toybox $i; done</b></p></blockquote></p> |
| |
| <p>When building from source, use the "<b>make install</b>" and |
| "<b>make install_flat</b>" |
| targets with an appropriate <b>PREFIX=/target/path</b> either |
| exported or on the make command line. When cross compiling, |
| "<b>make list</b>" outputs the command names enabled by defconfig. |
| For more information, see "<b>make help</b>".</p> |
| |
| <p>The command name "toybox" takes the second argument as the name of the |
| command to run, so "./toybox ls -l" also behaves like ls. The "toybox" |
| name is special in that it can have a suffix (toybox-i686 or toybox-1.2.3) |
| and still be recognized, so you can have multiple versions of toybox in the |
| same directory.</p> |
| |
| <p>When toybox doesn't recognize its |
| filename as a command, it dereferences one |
| level of symlink. So if your script needs "gsed" you can "ln -s sed gsed", |
| then when you run "gsed" toybox knows how to be "sed".</p> |
| |
| <hr /><h2><a name="dotslash" />Q: What's this ./ on the front of commands in your examples?</h2> |
| |
| <p>A: When you don't give a path to a command's executable file, |
| linux command shells search the directories listed in the $PATH envionment |
| variable (in order), which usually doesn't include the current directory |
| for security reasons. The |
| magic name "." indicates the current directory (the same way ".." means |
| the parent directory and starting with "/" means the root directory) |
| so "./file" gives a path to the executable file, and thus runs a command |
| out of the current directory where just typing "file" won't find it. |
| For historical reasons PATH is colon-separated, and treats an |
| empty entry (including leading/trailing colon) as "check the current |
| directory", so if you WANT to add the current directory to PATH you |
| can PATH="$PATH:" but doing so is a TERRIBLE idea.</p> |
| |
| <p>Toybox's shell (toysh) checks for built-in commands before looking at the |
| $PATH (using the standard "bash builtin" logic just with lots more builtins), |
| so "ls" doesn't have to exist in your filesystem for toybox to find it. When |
| you give a path to a command the shell won't run the built-in version |
| but will run the file at that location. (But the multiplexer command |
| won't: "toybox /bin/ls" runs the built-in ls, you can't point it at an |
| arbitrary file out of the filesystem and have it run that. You could |
| "toybox nice /bin/ls" though.)</p> |
| |
| <hr /><h2><a name="standalone" />Q: How do I make individual/standalone toybox command binaries?</h2> |
| |
| <p>After running the configure step (generally "make defconfig") |
| you can "make list" to see available command names you can use as build |
| targets to build just that command |
| (ala "make sed"). Commands built this way do not contain a multiplexer and |
| don't care what the command filename is.</p> |
| |
| <p>The "make change" target (as in change for a $20) builds every command |
| standalone (in the "change" subdirectory). Note that this is collectively |
| about 10 times as large as the multiplexer version, both in disk space and |
| runtime memory. (Even more when statically linked.)</p> |
| |
| <hr /><h2><a name="cross" />Q: How do I cross compile toybox?</h2> |
| |
| <p>A: You need a compiler "toolchain" capable of producing binaries that |
| run on your target. A toolchain is an |
| integrated suite of compiler, assembler, and linker, plus the standard |
| headers and |
| libraries necessary to build C programs. (And a few miscellaneous binaries like |
| nm and objdump.)</p> |
| |
| <p>Toybox is tested against two compilers (llvm, gcc) and three C libraries |
| (bionic, musl, glibc) in the following combinations:</p> |
| |
| <a name="cross1" /> |
| <p><a href="#cross1">1) gcc+glibc = host toolchain</a></p> |
| |
| <p>Most Linux distros come with that as a host compiler, which is used by |
| default when you build normally |
| (<b>make distclean defconfig toybox</b>, or <b>make menuconfig</b> followed |
| by <b>make</b>).</p> |
| |
| <p>You can use LDFLAGS=--static if you want static binaries, but static |
| glibc is hugely inefficient ("hello world" is 810k on x86-64) and throws a |
| zillion linker warnings because one of its previous maintainers |
| <a href=https://www.akkadia.org/drepper/no_static_linking.html>was insane</a> |
| (which meant at the time he refused to fix |
| <a href=https://elinux.org/images/2/2d/ELC2010-gc-sections_Denys_Vlasenko.pdf>obvious bugs</a>), plus it uses dlopen() at runtime to implement basic things like |
| <a href=https://stackoverflow.com/questions/15165306/compile-a-static-binary-which-code-there-a-function-gethostbyname>DNS lookup</a> (which is almost impossible |
| to support properly from a static binary because you wind up with two |
| instances of malloc() managing two heaps which corrupt as soon as a malloc() |
| from one is free()d into the other, although glibc added |
| <a href=https://stackoverflow.com/questions/14289488/use-dlsym-on-a-static-binary>improper support</a> which still requires the shared libraries to be |
| installed on the system alongside the static binary: |
| <a href=https://www.youtube.com/watch?v=Ih-3vK2qLls>in brief, avoid</a>). |
| These days glibc is <a href=https://blog.aurel32.net/175>maintained |
| by a committee</a> instead of a single |
| maintainer, if that's an improvement. (As with Windows and |
| Cobol, most people deal with it and get on with their lives.)</p> |
| |
| <a name="cross2" /> |
| <p><a href="#cross2">2) gcc+musl = musl-cross-make</a></p> |
| |
| <p>The cross compilers I test this with are built from the |
| <a href=http://musl.libc.org/>musl-libc</a> maintainer's |
| <a href=https://github.com/richfelker/musl-cross-make>musl-cross-make</a> |
| project, built by running toybox's scripts/mcm-buildall.sh in that directory, |
| and then symlink the resulting "ccc" subdirectory into toybox where |
| "make root CROSS=" can find them, ala:</p> |
| |
| <blockquote><b><pre> |
| cd ~ |
| git clone https://github.com/landley/toybox |
| git clone https://github.com/richfelker/musl-cross-make |
| cd musl-cross-make |
| ../toybox/scripts/mcm-buildall.sh # this takes a while |
| ln -s $(realpath ccc) ../toybox/ccc |
| </pre></b></blockquote> |
| |
| <p>Instead of symlinking ccc, you can specify a CROSS_COMPILE= prefix |
| in the same format the Linux kernel build uses. You can either provide a |
| full path in the CROSS_COMPILE string, or add the appropriate bin directory |
| to your $PATH. I.E:</p> |
| |
| <blockquote> |
| <b><p>make LDFLAGS=--static CROSS_COMPILE=~/musl-cross-make/ccc/m68k-linux-musl-cross/bin/m68k-linux-musl- distclean defconfig toybox</p></b> |
| </blockquote> |
| |
| <p>Is equivalent to:</p> |
| |
| <blockquote><b><p> |
| export "PATH=~/musl-cross-make/ccc/m68k-linux-musl-cross/bin:$PATH"<br /> |
| LDFLAGS=--static make distclean defconfig toybox CROSS=m68k-linux-musl- |
| </p></b></blockquote> |
| |
| <p>Note: these examples use static linking becausae a dynamic musl binary |
| won't run on your host unless you install musl's libc.so into the system |
| libraries (which is an accident waiting to happen adding a second C library |
| to most glibc linux distribution) or play with $LD_LIBRARY_PATH. |
| In theory you could "make root" a dynamic root filesystem with musl by copying |
| the shared libraries out of the toolchain, but I haven't bothered implementing |
| that in mkroot yet because a static linked musl hello world is 10k on x86 |
| (5k if stripped).</p> |
| |
| <a name="cross3" /> |
| <p><a href="#cross3">3) llvm+bionic = Android NDK</a></p> |
| |
| <p>The <a href=https://developer.android.com/ndk/downloads>Android |
| Native Development Kit</a> provides an llvm toolchain with the bionic |
| libc used by Android. To turn it into something toybox can use, you |
| just have to add an appropriately prefixed "cc" symlink to the other |
| prefixed tools, ala:</p> |
| |
| <blockquote><b><pre> |
| unzip android-ndk-r21b-linux-x86_64.zip |
| cd android-ndk-21b/toolchains/llvm/prebuilt/linux-x86_64/bin |
| ln -s x86_64-linux-android29-clang x86_64-linux-android-cc |
| PATH="$PWD:$PATH" |
| cd ~/toybox |
| make distclean |
| make LDFLAGS=--static CROSS_COMPILE=x86_64-linux-android- defconfig toybox |
| </pre></b></blockquote> |
| |
| <p>Again, you need to static link unless you want to install bionic on your |
| host. Binaries statically linked against bionic are almost as big as with |
| glibc, but at least it doesn't have the dlopen() issues. (You still can't |
| sanely use dlopen() from a static binary, but bionic doesn't use dlopen() |
| internally to implement basic features.)</p> |
| |
| <p>Note: although the resulting toybox will run in a standard |
| Linux system, even "hello world" |
| statically linked against bionic segfaults before calling main() |
| when /dev/null isn't present. This presents mkroot with a chicken and |
| egg problem for both chroot and qemu cases, because mkroot's init script |
| has to mount devtmpfs on /dev to provide /dev/null before the shell binary |
| can run mkroot's init script. |
| Since mkroot runs as a normal user, we can't "mknod dev/null" at build |
| time to create a "null" device in the filesystem we're packaging up so |
| initramfs doesn't start with an empty /dev, and the |
| <a href=https://lkml.org/lkml/2016/6/22/686>kernel</a> |
| <a href=https://lkml.org/lkml/2017/5/14/180>developers</a> |
| <a href=https://lkml.org/lkml/2017/9/13/651>repeatedly</a> |
| <a href=https://lkml.org/lkml/2020/5/14/1584>rejected</a> a patch to |
| make the Linux kernel honor DEVTMPFS_MOUNT in initramfs. Teaching toybox |
| cpio to accept synthetic filesystem metadata, |
| presumably in <a href=https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt>get_init_cpio</a> format, remains a todo item.</p> |
| |
| <hr /><h2><a name="system" />Q: What part of Linux/Android does toybox provide?</h2> |
| |
| <p>A: |
| Toybox is one of three packages (linux, libc, command line) which together provide a bootable unix-style command line operating system. |
| Toybox provides the "command line" part, with a |
| <a href=https://en.wikipedia.org/wiki/Bash_(Unix_shell)>bash</a> compatible |
| <a href=https://en.wikipedia.org/wiki/Unix_shell>command line interpreter</a> |
| and over two hundred <a href=https://landley.net/toybox/help.html>commands</a> |
| to call from it, as documented in |
| <a href=https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/>posix</a>, |
| the <a href=https://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cmdbehav.html>Linux Standard Base</a>, and the |
| <a href=https://man7.org/linux/man-pages/dir_section_1.html>Linux Manual |
| Pages</a>.</p> |
| |
| <p>Toybox is not by itself a complete operating system, it's a set of standard command line utilities that run in an operating system. |
| Booting a simple system to a shell prompt requires a kernel to drive the hardware (such as Linux, or BSD with a Linux emulation layer), programs for the system to run (such as toybox's commands), and a C library ("libc") to connect them together.</p> |
| |
| <p>Toybox has a policy of requiring no external dependencies other than the |
| kernel and C library (at least for defconfig builds). You can optionally enable support for |
| additional libraries in menuconfig (such as openssl, zlib, or selinux), |
| but toybox either provides its own built-in versions of such functionality |
| (which the libraries provide larger, more complex, often assembly optimized |
| alternatives to), or allows things like selinux support to cleanly drop |
| out.</p> |
| |
| <p>Static linking (with the --static option) copies library contents |
| into the resulting binary, creating larger but more portable programs which |
| can run even if they're the only file in the filesystem. Otherwise, |
| the "dynamically" linked programs require each shared library file to be |
| present on the target system, either copied out of the toolchain or built |
| again from source (with potential version skew if they don't match the toolchain |
| versions exactly), plus a dynamic linker executable installed at a specific |
| absolute path. See the |
| <a href=https://www.man7.org/linux/man-pages/man1/ldd.1.html>ldd</a>, |
| <a href=https://www.man7.org/linux/man-pages/man8/ld.so.8.html>ld.so</a>, |
| and <a href=https://www.man7.org/linux/man-pages/man7/libc.7.html>libc</a> |
| man pages for details.</p> |
| |
| <p>Most embedded systems will add another package to the kernel/libc/cmdline |
| above containing the dedicated "application" that the embedded system exists to |
| run, plus any other packages that application depends on. |
| Build systems add a native version of the toolchain packages so |
| they can compile additional software on the resulting system. Desktop systems |
| add a GUI and additional application packages like web browsers |
| and video players. A linux distro like Debian adds hundreds of packages. |
| Android adds around a thousand.</p> |
| |
| <p>But all of these systems conceptually sit on a common three-package |
| "kernel/libc/cmdline" base (often inefficiently implemented and broken up |
| into more packages), and toybox aims to provide a simple, reproducible, |
| auditable version of the cmdline portion of that base.</p> |
| |
| <hr /><h2><a name="mkroot" />Q: How do you build a working Linux system with toybox?</h2> |
| |
| <p>A: Toybox has a built-in <a href=https://github.com/landley/toybox/blob/master/scripts/mkroot.sh>system builder</a>, with the Makefile target "<b>make |
| root</b>". To enter the resulting root filesystem, "<b>sudo chroot |
| root/host/fs /init</b>". Type "exit" to get back out.</p> |
| |
| <p>You can cross compile simple three package (toybox+libc+linux) |
| systems configured to boot to a shell prompt under the emulator |
| <a href=https://qemu.org>qemu</a> |
| by specifying a target type with CROSS= |
| (or by setting CROSS_COMPILE= to a <a href=#cross>cross compiler</a> prefix with optional absolute |
| path), and pointing the build at a Linux kernel source directory, ala:</p> |
| |
| <blockquote><p><b>make root CROSS=sh4 LINUX=~/linux</b></p></blockquote> |
| |
| <p>Then you can <b>cd root/sh4; ./qemu-sh4.sh</b> to launch the emulator. |
| (You'll need the appropriate qemu-system-* emulator binary installed.) |
| Type "exit" when done and it should shut down the emulator on the way out, |
| similar to exiting the chroot version. (Except this is more like you ssh'd |
| to a remote machine: the emulator created its own CPU with its own memory |
| and I/O devices, and booted a kernel in it.)</p> |
| |
| <p>The build finds the <a href=#system>three packages</a> needed to produce |
| this system because 1) you're in a toybox source directory, 2) your cross |
| compiler has a libc built into it, 3) you tell it where to find a Linux kernel |
| source directory with LINUX= on the command line. If you don't say LINUX=, |
| it skips that part of the build and just produces a root filesystem directory |
| ala the first example in this FAQ answer.</p> |
| |
| <p>The CROSS= shortcut expects a "ccc" symlink in the toybox source directory |
| pointing at a directory full of cross compilers. The ones I test this with are built from the musl-libc |
| maintainer's |
| <a href=https://github.com/richfelker/musl-cross-make>musl-cross-make</a> |
| project, built by running toybox's scripts/mcm-buildall.sh in that directory, |
| and then symlink the resulting "ccc" subdirectory into toybox where CROSS= |
| can find them:</p> |
| |
| <blockquote><b><pre> |
| cd ~ |
| git clone https://github.com/landley/toybox |
| git clone https://github.com/richfelker/musl-cross-make |
| cd musl-cross-make |
| ../toybox/scripts/mcm-buildall.sh # this takes a while |
| ln -s $(realpath ccc) ../toybox/ccc |
| </pre></b></blockquote> |
| |
| <p>If you don't want to do that, you can download <a href=http://mkroot.musl.cc/latest/>prebuilt binary versions</a> from Zach van Rijn's site and |
| just extract them into a "ccc" subdirectory under the toybox source.</p> |
| |
| <p>Once you've installed the cross compilers, "<b>make root CROSS=help</b>" |
| should list all the available cross compilers it recognizes under ccc, |
| something like:</p> |
| |
| <blockquote><b><p> |
| aarch64 armv4l armv5l armv7l armv7m armv7r i486 i686 m68k microblaze mips mips64 mipsel powerpc powerpc64 powerpc64le s390x sh2eb sh4 x32 x86_64 |
| </p></b></blockquote> |
| |
| <p>(A long time ago I |
| <a href=http://landley.net/aboriginal/architectures.html>tried to explain</a> |
| what some of these architectures were.)</p> |
| |
| <p>You can build all the targets at once, and can add additonal packages |
| to the build, by calling the script directly and listing packages on |
| the command line:</p> |
| |
| <blockquote> |
| <p><b>scripts/mkroot.sh CROSS=all LINUX=~/linux dropbear</b></p> |
| </blockquote> |
| |
| <p>An example package build script (building the dropbear ssh server, adding a |
| port forward from 127.0.0.1:2222 to the qemu command line, and providing a |
| ssh2dropbear.sh convenience script to the output directory) is provided |
| in the scripts/root directory. If you add your own scripts elsewhere, just |
| give a path to them on the command line. (No, I'm not merging more package build |
| scripts, I <a href=https://speakerdeck.com/landley/developing-for-non-x86-targets-using-qemu?slide=78>learned that lesson</a> long ago. But if you |
| want to write your own, feel free.)</p> |
| |
| <p>(Note: currently mkroot.sh cheats. If you don't have a .config it'll |
| make defconfig and add CONFIG_SH and CONFIG_ROUTE to it, because the new |
| root filesystem kinda needs those commands to function properly. If you already |
| have a .config that |
| _doesn't_ have CONFIG_SH in it, you won't get a shell prompt or be able to run |
| the init script without a shell. This is currently a problem because sh |
| and route are still in pending and thus not in defconfig, so "make root" |
| cheats and adds them. I'm working on it. tl;dr if make root doesn't work |
| "rm .config" and run it again, and all this should be fixed up in future when |
| those two commands are promoted out of pending so "make defconfig" would have |
| what you need anyway. It's designed to let yout tweak your config, which is |
| why it uses the .config that's there when there is one, but the default is |
| currently wrong because it's not quite finished yet. All this should be |
| cleaned up in a future release, before 1.0.)</p> |
| |
| |
| |
| <!--#include file="footer.html" --> |