123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848 |
- <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="#targets">What architectures does toybox support?</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 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 that display info about <a href=https://en.wikipedia.org/wiki/Executable_and_Linkable_Format>ELF files</a>.)</p>
- <p>Toybox supports the standard $CROSS_COMPILE prefix environnment variable,
- same as the Linux kernel build uses. This is used to prefix all the tools
- (target-cc, target-ld, target-strip) during the build, meaning the prefix
- usually ends with a "-" that's easy to forget but kind of important
- ("target-cc" and "targetcc" are not the same name).</p>
- <p>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 CROSS_COMPILE=m68k-linux-musl- make distclean defconfig toybox
- </p></b></blockquote>
- <p>(Both of those examples use static linking so you can install just
- the single file to target, or test them with "qemu-m68k toybox". Feel free
- to dynamically link instead if you prefer, mkroot offers a "dynamic"
- add-on to copy the compiler's shared libraries into the new root
- filesystem.)</p>
- <p>Toybox's <a href=#mkroot>system builder</a> can use a simpler $CROSS
- variable to specify the target(s) to build for if you've installed
- <a href=#cross2>compatible</a> cross compilers under the "ccc" directory.
- Behind the scenes this uses wildcard expansion to set $CROSS_COMPILER to
- an appropriate path/prefix-.</p>
- <hr /><h2><a name="targets">Q: What architectures does toybox support?</h2>
- <p>Toybox runs on 64 bit and 32 bit processors, little endian and big endian,
- tries to respect alignment, and will enable nommu support when fork() is
- unavailable (or when TOYBOX_FORCE_NOMMU is enabled in the config to
- work around broken nommu toolchains), but otherwise tries to be
- processor agnostic (although some commands such as strace can't avoid
- a processor-specific if/else staircase.).</p>
- <P>Several commands (such as ps/top) are unavoidably full of Linux assumptions.
- Some subset of the commands have been made to run on BSD and MacOS X, and
- lib/portability.* and scripts/genconfig.sh exist to catch some known
- variations.</p>
- </p>
- <p>Each release gets tested against two compilers (llvm, gcc), three C
- libraries (bionic, musl, glibc), and a half-dozen different processor
- types, 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 just try to get on with their lives.)</p>
- <a name="cross2" />
- <p><a href="#cross2">2) gcc+musl = musl-cross-make</a></p>
- <p>These cross compilers 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 <a href=https://github.com/landley/toybox/blob/master/scripts/mcm-buildall.sh>scripts/mcm-buildall.sh</a> 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>Since this takes a long time to run, and builds lots of targets
- (cross and native), we've uploaded
- <a href=downloads/binaries/toolchains/latest>the resulting binaries</a>
- so you can wget and extract a tarball or two instead of
- compiling them all yourself. (See the README in that directory for details.
- Yes there's a big source tarball in there for license compliance reasons.)</p>
- <p>Instead of CROSS= you can also 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 because 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.
- (The <a href=https://github.com/landley/toybox/blob/master/scripts/root/dynamic>dynamic</a> package
- in mkroot copies the shared libraries out of the toolchain to create a dynamic
- linking environment in the root filesystem, but it's not nearly as well
- tested.)</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" -->
|