design.html 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. <html><head><title>The design of toybox</title></head>
  2. <!--#include file="header.html" -->
  3. <h2>Topics</h2>
  4. <ul>
  5. <li><a href=#goals><h3>Design Goals</h3></a></li>
  6. <li><a href=#portability><h3>Portability Issues</h3></a></li>
  7. <li><a href=#license><h3>License</a></h3></a></li>
  8. <li><a href=#codestyle><h3>Coding Style</h3></a></li>
  9. </ul>
  10. <hr />
  11. <a name="goals"><b><h2><a href="#goals">Design goals</a></h2></b>
  12. <p>Toybox should be simple, small, fast, and full featured. In that order.</p>
  13. <p>It should be possible to get about <a href=https://en.wikipedia.org/wiki/Pareto_principle>80% of the way</a> to each goal
  14. before they really start to fight.
  15. When these goals need to be balanced off against each other, keeping the code
  16. as simple as it can be to do what it does is the most important (and hardest)
  17. goal. Then keeping it small is slightly more important than making it fast.
  18. Features are the reason we write code in the first place but this has all
  19. been implemented before so if we can't do a better job why bother?</p>
  20. <b><h3>Features</h3></b>
  21. <p>Toybox should provide the command line utilities of a build
  22. environment capable of recompiling itself under itself from source code.
  23. This minimal build system conceptually consists of 4 parts: toybox,
  24. a C library, a compiler, and a kernel. Toybox needs to provide all the
  25. commands (with all the behavior) necessary to run the configure/make/install
  26. of each package and boot the resulting system into a usable state.</p>
  27. <p>In addition, it should be possible to bootstrap up to arbitrary complexity
  28. under the result by compiling and installing additional packages into this
  29. minimal system, as measured by building both Linux From Scratch and the
  30. Android Open Source Project under the result. Any "circular dependencies"
  31. should be solved by toybox including the missing dependencies itself
  32. (see "Shared Libraries" below).</p>
  33. <p>Toybox may also provide some "convenience" utilties
  34. like top and vi that aren't necessarily used in a build but which turn
  35. the minimal build environment into a minimal development environment
  36. (supporting edit/compile/test cycles in a text console), configure
  37. network infrastructure for communication with other systems (in a build
  38. cluster), and so on.</p>
  39. <p>And these days toybox is the command line of Android, so anything the android
  40. guys say to do gets at the very least closely listened to.</p>
  41. <p>The hard part is deciding what NOT to include. A project without boundaries
  42. will bloat itself to death. One of the hardest but most important things a
  43. project must do is draw a line and say "no, this is somebody else's problem,
  44. not something we should do."
  45. Some things are simply outside the scope of the project: even though
  46. posix defines commands for compiling and linking, we're not going to include
  47. a compiler or linker (and support for a potentially infinite number of hardware
  48. targets). And until somebody comes up with a ~30k ssh implementation (with
  49. a crypto algorithm that won't need replacing every 5 years), we're
  50. going to point you at dropbear or bearssl.</p>
  51. <p>The <a href=roadmap.html>roadmap</a> has the list of features we're
  52. trying to implement, and the reasons why we decided to include those
  53. features. After the 1.0 release some of that material may get moved here,
  54. but for now it needs its own page. The <a href=status.html>status</a>
  55. page shows the project's progress against the roadmap.</p>
  56. <p>There are potential features (such as a screen/tmux implementation)
  57. that might be worth adding after 1.0, in part because they could share
  58. infrastructure with things like "less" and "vi" so might be less work for
  59. us to do than for an external from scratch implementation. But for now, major
  60. new features outside posix, android's existing commands, and the needs of
  61. development systems, are a distraction from the 1.0 release.</p>
  62. <b><h3>Speed</h3></b>
  63. <p>Quick smoketest: use the "time" command, and if you haven't got a test
  64. case that's embarassing enough to motivate digging, move on.</p>
  65. <p>It's easy to say a lot about optimizing for speed (which is why this section
  66. is so long), but at the same time it's the optimization we care the least about.
  67. The essence of speed is being as efficient as possible, which means doing as
  68. little work as possible. A design that's small and simple gets you 90% of the
  69. way there, and most of the rest is either fine-tuning or more trouble than
  70. it's worth (and often actually counterproductive). Still, here's some
  71. advice:</p>
  72. <p>First, understand the darn problem you're trying to solve. You'd think
  73. I wouldn't have to say this, and yet. Trying to find a faster sorting
  74. algorithm is no substitute for figuring out a way to skip the sorting step
  75. entirely. The fastest way to do anything is not to have to do it at all,
  76. and _all_ optimization boils down to avoiding unnecessary work.</p>
  77. <p>Speed is easy to measure; there are dozens of profiling tools for Linux,
  78. but sticking in calls to "millitime()" out of lib.c and subtracting
  79. (or doing two clock_gettime() calls and then nanodiff() on them) is
  80. quick and easy. Don't waste too much time trying to optimize something you
  81. can't measure, and there's no much point speeding up things you don't spend
  82. much time doing anyway.</p>
  83. <p>Understand the difference between throughput and latency. Faster
  84. processors improve throughput, but don't always do much for latency.
  85. After 30 years of Moore's Law, most of the remaining problems are latency,
  86. not throughput. (There are of course a few exceptions, like data compression
  87. code, encryption, rsync...) Worry about throughput inside long-running
  88. loops, and worry about latency everywhere else. (And don't worry too much
  89. about avoiding system calls or function calls or anything else in the name
  90. of speed unless you are in the middle of a tight loop that's you've already
  91. proven isn't running fast enough.)</p>
  92. <p>The lowest hanging optimization fruit is usually either "don't make
  93. unnecessary copies of data" or "use a reasonable block size in your
  94. I/O transactions instead of byte-at-a-time".
  95. Start by looking for those, most of the rest of this advice is just explaining
  96. why they're bad.</p>
  97. <p>"Locality of reference" is generally nice, in all sorts of contexts.
  98. It's obvious that waiting for disk access is 1000x slower than doing stuff in
  99. RAM (and making the disk seek is 10x slower than sequential reads/writes),
  100. but it's just as true that a loop which stays in L1 cache is many times faster
  101. than a loop that has to wait for a DRAM fetch on each iteration. Don't worry
  102. about whether "&" is faster than "%" until your executable loop stays in L1
  103. cache and the data access is fetching cache lines intelligently. (To
  104. understand DRAM, L1, and L2 cache, read Hannibal's marvelous ram guide at Ars
  105. Technica:
  106. <a href=http://arstechnica.com/paedia/r/ram_guide/ram_guide.part1-2.html>part one</a>,
  107. <a href=http://arstechnica.com/paedia/r/ram_guide/ram_guide.part2-1.html>part two</a>,
  108. <a href=http://arstechnica.com/paedia/r/ram_guide/ram_guide.part3-1.html>part three</a>,
  109. plus this
  110. <a href=http://arstechnica.com/articles/paedia/cpu/caching.ars/1>article on
  111. cacheing</a>, and this one on
  112. <a href=http://arstechnica.com/articles/paedia/cpu/bandwidth-latency.ars>bandwidth
  113. and latency</a>.
  114. And there's <a href=http://arstechnica.com/paedia/index.html>more where that came from</a>.)
  115. Running out of L1 cache can execute one instruction per clock cycle, going
  116. to L2 cache costs a dozen or so clock cycles, and waiting for a worst case dram
  117. fetch (round trip latency with a bank switch) can cost thousands of
  118. clock cycles. (Historically, this disparity has gotten worse with time,
  119. just like the speed hit for swapping to disk. These days, a _big_ L1 cache
  120. is 128k and a big L2 cache is a couple of megabytes. A cheap low-power
  121. embedded processor may have 8k of L1 cache and no L2.)</p>
  122. <p>Learn how <a href=http://nommu.org/memory-faq.txt>virtual memory and
  123. memory managment units work</a>. Don't touch
  124. memory you don't have to. Even just reading memory evicts stuff from L1 and L2
  125. cache, which may have to be read back in later. Writing memory can force the
  126. operating system to break copy-on-write, which allocates more memory. (The
  127. memory returned by malloc() is only a virtual allocation, filled with lots of
  128. copy-on-write mappings of the zero page. Actual physical pages get allocated
  129. when the copy-on-write gets broken by writing to the virtual page. This
  130. is why checking the return value of malloc() isn't very useful anymore, it
  131. only detects running out of virtual memory, not physical memory. Unless
  132. you're using a <a href=http://nommu.org>NOMMU system</a>, where all bets
  133. are off.)</p>
  134. <p>Don't think that just because you don't have a swap file the system can't
  135. start swap thrashing: any file backed page (ala mmap) can be evicted, and
  136. there's a reason all running programs require an executable file (they're
  137. mmaped, and can be flushed back to disk when memory is short). And long
  138. before that, disk cache gets reclaimed and has to be read back in. When the
  139. operating system really can't free up any more pages it triggers the out of
  140. memory killer to free up pages by killing processes (the alternative is the
  141. entire OS freezing solid). Modern operating systems seldom run out of
  142. memory gracefully.</p>
  143. <p>It's usually better to be simple than clever. Many people think that mmap()
  144. is faster than read() because it avoids a copy, but twiddling with the memory
  145. management is itself slow, and can cause unnecessary CPU cache flushes. And
  146. if a read faults in dozens of pages sequentially, but your mmap iterates
  147. backwards through a file (causing lots of seeks, each of which your program
  148. blocks waiting for), the read can be many times faster. On the other hand, the
  149. mmap can sometimes use less memory, since the memory provided by mmap
  150. comes from the page cache (allocated anyway), and it can be faster if you're
  151. doing a lot of different updates to the same area. The moral? Measure, then
  152. try to speed things up, and measure again to confirm it actually _did_ speed
  153. things up rather than made them worse. (And understanding what's really going
  154. on underneath is a big help to making it happen faster.)</p>
  155. <p>Another reason to be simple than clever is optimization
  156. strategies change with time. For example, decades ago precalculating a table
  157. of results (for things like isdigit() or cosine(int degrees)) was clearly
  158. faster because processors were so slow. Then processors got faster and grew
  159. math coprocessors, and calculating the value each time became faster than
  160. the table lookup (because the calculation fit in L1 cache but the lookup
  161. had to go out to DRAM). Then cache sizes got bigger (the Pentium M has
  162. 2 megabytes of L2 cache) and the table fit in cache, so the table became
  163. fast again... Predicting how changes in hardware will affect your algorithm
  164. is difficult, and using ten year old optimization advice can produce
  165. laughably bad results. Being simple and efficient should give at least a
  166. reasonable starting point.</p>
  167. <p>Even at the design level, a lot of simple algorithms scale terribly but
  168. perform fine with small data sets. When small datasets are the common case,
  169. "better" versions that trade higher throughput for worse latency can
  170. consistently perform worse.
  171. So if you think you're only ever going to feed the algorithm small data sets,
  172. maybe just do the simple thing and wait for somebody to complain. For example,
  173. you probably don't need to sort and binary search the contents of
  174. /etc/passwd, because even 50k users is still a reasonably manageable data
  175. set for a readline/strcmp loop, and that's the userbase of a fairly major
  176. <a href=https://en.wikipedia.org/wiki/List_of_United_States_public_university_campuses_by_enrollment>university</a>.
  177. Instead commands like "ls" call bufgetpwuid() out of lib/lib.c
  178. which keeps a linked list of recently seen items, avoiding reparsing entirely
  179. and trusting locality of reference to bring up the same dozen or so entries
  180. for "ls -l /dev" or similar. The pathological failure mode of "simple
  181. linked list" is to perform exactly as badly as constantly rescanning a
  182. huge /etc/passwd, so this simple optimization shouldn't ever make performance
  183. worse (modulo possible memory exhaustion and thus swap thrashing).
  184. On the other hand, toybox's multiplexer does sort and binary
  185. search its command list to minimize the latency of each command startup,
  186. because the sort is a compile-time cost done once per build,
  187. and the whole of command startup
  188. is a "hot path" that should do as little work as possible because EVERY
  189. command has to go through it every time before performing any other function
  190. so tiny gains are worthwhile. (These decisions aren't perfect, the point is
  191. to show that thought went into them.)</p>
  192. <p>The famous quote from Ken Thompson, "When in doubt, use brute force",
  193. applies to toybox. Do the simple thing first, do as little of it as possible,
  194. and make sure it's right. You can always speed it up later.</p>
  195. <b><h3>Size</h3></b>
  196. <p>Quick smoketest: build toybox with and without the command (or the change),
  197. and maybe run "nm --size-sort" on files in generated/unstripped.
  198. (See make bloatcheck below for toybox's built in nm size diff-er.)</p>
  199. <p>Again, being simple gives you most of this. An algorithm that does less work
  200. is generally smaller. Understand the problem, treat size as a cost, and
  201. get a good bang for the byte.</p>
  202. <p>What "size" means depends on context: there are at least a half dozen
  203. different metrics in two broad categories: space used on disk/flash/ROM,
  204. and space used in memory at runtime.</p>
  205. <p>Your executable file has at least
  206. four main segments (text = executable code, rodata = read only data,
  207. data = writeable variables initialized to a value other than zero,
  208. bss = writeable data initialized to zero). Text and rodata are shared between multiple instances of the program running
  209. simultaneously, the other 4 aren't. Only text, rodata, and data take up
  210. space in the binary, bss, stack and heap only matter at runtime. You can
  211. view toybox's symbols with "nm generated/unstripped/toybox", the T/R/D/B
  212. lets you know the segment the symbol lives in. (Lowercase means it's
  213. local/static.)</p>
  214. <p>Then at runtime there's
  215. heap size (where malloc() memory lives) and stack size (where local
  216. variables and function call arguments and return addresses live). And
  217. on 32 bit systems mmap() can have a constrained amount of virtual memory
  218. (usually a couple gigabytes: the limits on 64 bit systems are generally big
  219. enough it doesn't come up)</p>
  220. <p>Optimizing for binary size is generally good: less code is less to go
  221. wrong, and executing fewer instructions makes your program run faster (and
  222. fits more of it in cache). On embedded systems, binary size is especially
  223. precious because flash is expensive and code may need binary auditing for
  224. security. Small stack size
  225. is important for nommu systems because they have to preallocate their stack
  226. and can't make it bigger via page fault. And everybody likes a small heap.</p>
  227. <p>Measure the right things. Especially with modern optimizers, expecting
  228. something to be smaller is no guarantee it will be after the compiler's done
  229. with it. Will total binary size is the final result, it isn't always the most
  230. accurate indicator of the impact of a given change, because lots of things
  231. get combined and rounded during compilation and linking (and things like
  232. ASAN disable optimization). Toybox has scripts/bloatcheck to compare two versions
  233. of a program and show size changes in each symbol (using "nm --size-sort").
  234. You can "make baseline" to build a baseline version to compare against,
  235. and then apply your changes and "make bloatcheck" to compare against
  236. the saved baseline version.</p>
  237. <p>Avoid special cases. Whenever you see similar chunks of code in more than
  238. one place, it might be possible to combine them and have the users call shared
  239. code (perhaps out of lib/*.c). This is the most commonly cited trick, which
  240. doesn't make it easy to work out HOW to share. If seeing two lines of code do
  241. the same thing makes you slightly uncomfortable, you've got the right mindset,
  242. but "reuse" requires the "re" to have benefit, and infrastructure in search
  243. of a user will generally bit-rot before it finds one.</p>
  244. <p>The are a lot of potential microoptimizations (on some architectures
  245. using char instead of int as a loop index is noticeably slower, on some
  246. architectures C bitfields are surprisingly inefficient, & is often faster
  247. than % in a tight loop, conditional assignment avoids branch prediction
  248. failures...) but they're generally not worth doing unless you're trying to
  249. speed up the middle of a tight inner loop chewing through a large amount
  250. of data (such as a compression algorithm). For data pumps sane blocking
  251. and fewer system calls (buffer some input/output and do a big read/write
  252. instead of a bunch of little small ones) is usually the big win. But
  253. be careful about cacheing stuff: the two persistently hard problems in computer
  254. science are naming things, cache coherency, and off by one errors.</p>
  255. <b><h3>Simplicity</h3></b>
  256. <p>Complexity is a cost, just like code size or runtime speed. Treat it as
  257. a cost, and spend your complexity budget wisely. (Sometimes this means you
  258. can't afford a feature because it complicates the code too much to be
  259. worth it.)</p>
  260. <p>Simplicity has lots of benefits. Simple code is easy to maintain, easy to
  261. port to new processors, easy to audit for security holes, and easy to
  262. understand.</p>
  263. <p>Simplicity itself can have subtle non-obvious aspects requiring a tradeoff
  264. between one kind of simplicity and another: simple for the computer to
  265. execute and simple for a human reader to understand aren't always the
  266. same thing. A compact and clever algorithm that does very little work may
  267. not be as easy to explain or understand as a larger more explicit version
  268. requiring more code, memory, and CPU time. When balancing these, err on the
  269. side of doing less work, but add comments describing how you
  270. could be more explicit.</p>
  271. <p>In general, comments are not a substitute for good code (or well chosen
  272. variable or function names). Commenting "x += y;" with "/* add y to x */"
  273. can actually detract from the program's readability. If you need to describe
  274. what the code is doing (rather than _why_ it's doing it), that means the
  275. code itself isn't very clear.</p>
  276. <p>Environmental dependencies are another type of complexity, so needing other
  277. packages to build or run is a big downside. For example, we don't use curses
  278. when we can simply output ansi escape sequences and trust all terminal
  279. programs written in the past 30 years to be able to support them. Regularly
  280. testing that we work with C libraries which support static linking (musl does,
  281. glibc doesn't) is another way to be self-contained with known boundaries:
  282. it doesn't have to be the only way to build the project, but should be regularly
  283. tested and supported.</p>
  284. <p>Prioritizing simplicity tends to serve our other goals: simplifying code
  285. generally reduces its size (both in terms of binary size and runtime memory
  286. usage), and avoiding unnecessary work makes code run faster. Smaller code
  287. also tends to run faster on modern hardware due to CPU cacheing: fitting your
  288. code into L1 cache is great, and staying in L2 cache is still pretty good.</p>
  289. <p>But a simple implementation is not always the smallest or fastest, and
  290. balancing simplicity vs the other goals can be difficult. For example, the
  291. atolx_range() function in lib/lib.c always uses the 64 bit "long long" type,
  292. which produces larger and slower code on 32 bit platforms and
  293. often assigned into smaller interger types. Although libc has parallel
  294. implementations for different data sizes (atoi, atol, atoll) we chose a
  295. common codepath which can cover all cases (every user goes through the
  296. same codepath, with the maximum amount of testing and minimum and avoids
  297. surprising variations in behavior).</p>
  298. <p>On the other hand, the "tail" command has two codepaths, one for seekable
  299. files and one for nonseekable files. Although the nonseekable case can handle
  300. all inputs (and is required when input comes from a pipe or similar, so cannot
  301. be removed), reading through multiple gigabytes of data to reach the end of
  302. seekable files was both a common case and hugely penalized by a nonseekable
  303. approach (half-minute wait vs instant results). This is one example
  304. where performance did outweigh simplicity of implementation.</p>
  305. <p><a href=http://www.joelonsoftware.com/articles/fog0000000069.html>Joel
  306. Spolsky argues against throwing code out and starting over</a>, and he has
  307. good points: an existing debugged codebase contains a huge amount of baked
  308. in knowledge about strange real-world use cases that the designers didn't
  309. know about until users hit the bugs, and most of this knowledge is never
  310. explicitly stated anywhere except in the source code.</p>
  311. <p>That said, the Mythical Man-Month's "build one to throw away" advice points
  312. out that until you've solved the problem you don't properly understand it, and
  313. about the time you finish your first version is when you've finally figured
  314. out what you _should_ have done. (The corrolary is that if you build one
  315. expecting to throw it away, you'll actually wind up throwing away two. You
  316. don't understand the problem until you _have_ solved it.)</p>
  317. <p>Joel is talking about what closed source software can afford to do: Code
  318. that works and has been paid for is a corporate asset not lightly abandoned.
  319. Open source software can afford to re-implement code that works, over and
  320. over from scratch, for incremental gains. Before toybox, the unix command line
  321. has already been reimplemented from scratch several times (the
  322. original AT&amp;T Unix command line in assembly and then in C, the BSD
  323. versions, Coherent was the first full from-scratch Unix clone in 1980,
  324. Minix was another clone which Linux was inspired by and developed under,
  325. the GNU tools were yet another rewrite intended for use in the stillborn
  326. "Hurd" project, BusyBox was still another rewrite, and more versions
  327. were written in Plan 9, uclinux, klibc, sash, sbase, s6, and of course
  328. android toolbox...). But maybe toybox can do a better job. :)</p>
  329. <p>As Antoine de St. Exupery (author of "The Little Prince" and an early
  330. aircraft designer) said, "Perfection is achieved, not when there
  331. is nothing left to add, but when there is nothing left to take away."
  332. And Ken Thompson (creator of Unix) said "One of my most productive
  333. days was throwing away 1000 lines of code." It's always possible to
  334. come up with a better way to do it.</p>
  335. <p>P.S. How could I resist linking to an article about
  336. <a href=http://blog.outer-court.com/archive/2005-08-24-n14.html>why
  337. programmers should strive to be lazy and dumb</a>?</p>
  338. <hr>
  339. <a name="portability"><b><h2><a href="#portability">Portability issues</a></h2></b>
  340. <b><h3>Platforms</h3></b>
  341. <p>Toybox should run on Android (all commands with musl-libc, as large a subset
  342. as practical with bionic), and every other hardware platform Linux runs on.
  343. Other posix/susv4 environments (perhaps MacOS X or newlib+libgloss) are vaguely
  344. interesting but only if they're easy to support; I'm not going to spend much
  345. effort on them.</p>
  346. <p>I don't do windows.</p>
  347. <a name="standards" />
  348. <b><h3>Standards</h3></b>
  349. <p>Toybox is implemented with reference to
  350. <a href=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf>c11</a>,
  351. <a href=roadmap.html#susv4>Posix 2008</a>,
  352. <a href=#bits>LP64</a>,
  353. <a href=roadmap.html#sigh>LSB 4.1</a>,
  354. the <a href=https://www.kernel.org/doc/man-pages/>Linux man pages</a>,
  355. various <a href=https://www.rfc-editor.org/rfc-index.html>IETF RFCs</a>,
  356. the linux kernel source's
  357. <a href=https://www.kernel.org/doc/Documentation/>Documentation</a> directory,
  358. utf8 and unicode, and our terminal control outputs ANSI
  359. <a href=https://man7.org/linux/man-pages/man4/console_codes.4.html>escape sequences</a>.
  360. Toybox gets <a href=faq.html#cross>tested</a> with gcc and llvm on glibc,
  361. musl-libc, and bionic, plus occasional <a href=https://github.com/landley/toybox/blob/master/kconfig/freebsd_miniconfig>FreeBSD</a> and
  362. <a href=https://github.com/landley/toybox/blob/master/kconfig/macos_miniconfig>MacOS</a> builds for subsets
  363. of the commands.</p>
  364. <p>For the build environment and runtime environment, toybox depends on
  365. posix-2008 libc features such as the openat() family of
  366. functions. We also root around in the linux /proc directory a lot (no other
  367. way to implement "ps" at the moment), and assume certain "modern" linux kernel
  368. behavior (for example <a href=https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b6a2fea39318>linux 2.6.22</a>
  369. expanded the 128k process environment size limit to 2 gigabytes, then it was
  370. trimmed back down to 10 megabytes, and when I asked for a way to query the
  371. actual value from the kernel if it was going to keep changing
  372. like that <a href=https://lkml.org/lkml/2017/11/5/204>Linus declined</a>).
  373. We make an effort to support <a href=faq.html#support_horizon>older kernels</a>
  374. and other implementations (primarily MacOS and BSD) but we don't always
  375. police their corner cases very closely.</p>
  376. <p><b>Why not just use the newest version of each standard?</b>
  377. <p>Partly to <a href=faq.html#support_horizon>support older systems</a>:
  378. you can't fix a bug in the old system if you can't build in the old
  379. environment.</p>
  380. <p>Partly because toybox's maintainer has his own corollary to Moore's law:
  381. 50% of what you know about programming the hardware is obsolete every 18
  382. months, but the advantage of C &amp; Unix it's usually the same 50% cycling
  383. out over and over.</p>
  384. <p>But mostly because the updates haven't added anything we care about.
  385. Posix-2008 switched some things to larger (64 bit) data types and added the
  386. openat() family of functions (which take a directory filehandle instead of
  387. using the Current Working Directory),
  388. but the 2013 and 2018 releases of posix were basically typo fixes: still
  389. release 7, still SUSv4. (An eventual release 8 might be interesting but
  390. it's not out yet.)</p>
  391. <p>We're nominally C11 but mostly just writing good old ANSI C (I.E. C89).
  392. We use a few of the new features like compound literals (6.5.2.5) and structure
  393. initialization by member name with unnamed members zeroed (6.7.9),
  394. but mostly we "officially" went from c99 to C11 to work around a
  395. <a href=https://github.com/landley/toybox/commit/3625a260065b>clang compiler bug</a>.
  396. The main thing we use from c99 that c89 hadn't had was // single line comments.
  397. (We mostly don't even use C99's explicit width data types, ala uint32_t and
  398. friends, because LP64 handles that for us.)</p>
  399. <p>We're ignoring new versions of the Linux Foundation's standards (LSB, FHS)
  400. entirely, for the same reason Debian is: they're not good at maintaining
  401. standards. (The Linux Foundation acquiring the Free Standards Group worked
  402. out about as well as Microsoft buying Nokia, Twitter buying Vine, Yahoo
  403. buying Flickr...)</p>
  404. <p>We refer to current versions of man7.org because it's
  405. not easily versioned (the website updates regularly) and because
  406. Michael Kerrisk does a good job maintaining it so far. That said, we
  407. try to "provide new" in our commands but "depend on old" in our build scripts.
  408. (For example, we didn't start using "wait -n" until it had been in bash for 7
  409. years, and even then people depending on Centos' 10 year support horizon
  410. complained.)</p>
  411. <p>Using newer vs older RFCs, and upgrading between versions, is a per-case
  412. judgement call.</p>
  413. <p><b>How strictly do you adhere to these standards?</b>
  414. <p>...ish? The man pages have a lot of stuff that's not in posix,
  415. and there's no "init" or "mount" in posix, you can't implement "ps"
  416. without replying on non-posix APIs....</p>
  417. <p>When the options a command offers visibly contradict posix, we try to have
  418. a "deviations from posix" section at the top of the source listing the
  419. differences, but that's about what we provide not what we used from the OS
  420. or build environment.</p>
  421. <p>The build needs bash (not a pure-posix sh), and building on MacOS requires
  422. "gsed" (because Mac's sed is terrible), but toybox is explicitly self-hosting
  423. and any failure to build under the tool versions we provide would be a bug
  424. needing to be fixed.</p>
  425. <p>Within the code, everything in main.c and lib/*.c has to build
  426. on every supported Linux version, compiler, and library, plus BSD and MacOS.
  427. We mostly try to keep #if/else staircases for portability issues to
  428. lib/portability.[ch].</p>
  429. <p>Portability of individual commands varies: we sometimes program directly
  430. against linux kernel APIs (unavoidable when accessing /proc and /sys),
  431. individual commands are allowed to #include &lt;linux/*.h&gt; (common
  432. headers and library files are not, except maybe lib/portability.* within an
  433. appropriate #ifdef), we only really test against Linux errno values
  434. (unless somebody on BSD submits a bug), and a few commands outright cheat
  435. (the way ifconfig checks for ioctl numbers in the 0x89XX range). This is
  436. the main reason some commands build on BSD/MacOS and some don't.</p>
  437. <a name="bits" />
  438. <b><h3>32/64 bit</h3></b>
  439. <p>Toybox should work on both 32 bit and 64 bit systems. 64 bit desktop
  440. hardware went mainstream <a href=https://web.archive.org/web/20040307000108mp_/http://developer.intel.com/technology/64bitextensions/faq.htm>in 2005</a>
  441. and was essentially ubiquitous <a href=faq.html#support_horizon>by 2012</a>,
  442. but 32 bit hardware will continue to be important in embedded devices for years to come.</p>
  443. <p>Toybox relies on the
  444. <a href=http://archive.opengroup.org/public/tech/aspen/lp64_wp.htm>LP64 standard</a>
  445. which Linux, MacOS X, and BSD all implement, and which modern 64 bit processors such as
  446. x86-64 were <a href=http://www.pagetable.com/?p=6>explicitly designed to
  447. support</a>. (Here's the original <a href=https://web.archive.org/web/20020905181545/http://www.unix.org/whitepapers/64bit.html>LP64 white paper</a>.)</p>
  448. <p>LP64 defines explicit sizes for all the basic C integer types, and
  449. guarantees that on any Unix-like platform "long" and "pointer" types
  450. are always the same size (the processor's register size).
  451. This means it's safe to assign pointers into
  452. longs and vice versa without losing data: on 32 bit systems both are 32 bit,
  453. on 64 bit systems both are 64 bit.</p>
  454. <table border=1 cellpadding=10 cellspacing=2>
  455. <tr><td>C type</td><td>char</td><td>short</td><td>int</td><td>long</td><td>long long</td></tr>
  456. <tr><td>32 bit<br />sizeof</td><td>8 bits</td><td>16 bits</td><td>32 bits</td><td>32 bits</td><td>64 bits</td></tr>
  457. <tr><td>64 bit<br />sizeof</td><td>8 bits</td><td>16 bits</td><td>32 bits</td><td>64 bits</td><td>64 bits</td></tr>
  458. </table>
  459. <p>LP64 eliminates the need to use c99 "uint32_t" and friends: the basic
  460. C types all have known size/behavior, and the only type whose
  461. size varies is "long", which is the natural register size of the processor.</p>
  462. <p>Note that Windows doesn't work like this, and I don't care, but if you're
  463. curious here are <a href=https://devblogs.microsoft.com/oldnewthing/20050131-00/?p=36563>the insane legacy reasons why this is broken on Windows</a>.</a></p>
  464. <p>The main squishy bit in LP64 is that "long long" was defined as
  465. "at least" 64 bits instead of "exactly" 64 bits, and the standards body
  466. that issued it collapsed in the wake of the <a href=https://en.wikipedia.org/wiki/Unix_wars>proprietary unix wars</a> (all
  467. those lawsuits between AT&amp;T/BSDI/Novell/Caldera/SCO), so is
  468. not available to issue an official correction. Then again a processor
  469. with 128-bit general purpose registers wouldn't be commercially viable
  470. <a href=https://landley.net/notes-2011.html#26-06-2011>until 2053</a>
  471. (because 2005+32*1.5), and with the S-curve of Moore's Law slowly
  472. <a href=http://www.acm.org/articles/people-of-acm/2016/david-patterson>bending back down</a> as
  473. atomic limits and <a href=http://www.cnet.com/news/end-of-moores-law-its-not-just-about-physics/>exponential cost increases</a> produce increasing
  474. drag.... (The original Moore's Law curve would mean that in the year 2022
  475. a high end workstation would have around 8 terabytes of RAM, available retail.
  476. Most don't even come with
  477. that much disk space.) At worst we don't need to care for decades, the
  478. S-curve bending down means probably not in our lifetimes, and
  479. atomic limits may mean "never". So I'm ok treating "long long" as exactly 64 bits.</p>
  480. <b><h3>Signedness of char</h3></b>
  481. <p>On platforms like x86, variables of type char default to unsigned. On
  482. platforms like arm, char defaults to signed. This difference can lead to
  483. subtle portability bugs, and to avoid them we specify which one we want by
  484. feeding the compiler -funsigned-char.</p>
  485. <p>The reason to pick "unsigned" is that way char strings are 8-bit clean by
  486. default, which makes UTF-8 support easier.</p>
  487. <p><h3>Error messages and internationalization:</h3></p>
  488. <p>Error messages are extremely terse not just to save bytes, but because we
  489. don't use any sort of _("string") translation infrastructure. (We're not
  490. translating the command names themselves, so we must expect a minimum amount of
  491. english knowledge from our users, but let's keep it to a minimum.)</p>
  492. <p>Thus "bad -A '%c'" is
  493. preferable to "Unrecognized address base '%c'", because a non-english speaker
  494. can see that -A was the problem (giving back the command line argument they
  495. supplied). A user with a ~20 word english vocabulary is
  496. more likely to know (or guess) "bad" than the longer message, and you can
  497. use "bad" in place of "invalid", "inappropriate", "unrecognized"...
  498. Similarly when atolx_range() complains about range constraints with
  499. "4 < 17" or "12 > 5", it's intentional: those don't need to be translated.</p>
  500. <p>The strerror() messages produced by perror_exit() and friends should be
  501. localized by libc, and our error functions also prepend the command name
  502. (which non-english speakers can presumably recognize already). Keep the
  503. explanation in between to a minimum, and where possible feed back the values
  504. they passed in to identify _what_ we couldn't process.
  505. If you say perror_exit("setsockopt"), you've identified the action you
  506. were trying to take, and the perror gives a translated error message (from libc)
  507. explaining _why_ it couldn't do it, so you probably don't need to add english
  508. words like "failed" or "couldn't assign".</p>
  509. <p>All commands should be 8-bit clean, with explicit
  510. <a href=http://yarchive.net/comp/linux/utf8.html>UTF-8</a> support where
  511. necessary. Assume all input data might be utf8, and at least preserve
  512. it and pass it through. (For this reason, our build is -funsigned-char on
  513. all architectures; "char" is unsigned unless you stick "signed" in front
  514. of it.)</p>
  515. <p>Locale support isn't currently a goal; that's a presentation layer issue
  516. (I.E. a GUI problem).</p>
  517. <p>Someday we should probably have translated --help text, but that's a
  518. post-1.0 issue.</p>
  519. <p><h3>Shared Libraries</h3></p>
  520. <p>Toybox's policy on shared libraries is that they should never be
  521. required, but can optionally be used to improve performance.</p>
  522. <p>Toybox should provide the command line utilities for
  523. <a href=roadmap.html#dev_env>self-hosting development envirionments</a>,
  524. and an easy way to set up "hermetic builds" (I.E. builds which provide
  525. their own dependencies, isolating the build logic from host command version
  526. skew with a simple known build environment). In both cases, external
  527. dependencies defeat the purpose.</p>
  528. <p>This means toybox should provide full functionality without relying
  529. on any external dependencies (other than libc). But toybox may optionally use
  530. libraries such as zlib and openssl to improve performance for things like
  531. deflate and sha1sum, which lets the corresponding built-in implementations
  532. be simple (and thus slow). But the built-in implementations need to exist and
  533. work.</p>
  534. <p>(This is why we use an external https wrapper program, because depending on
  535. openssl or similar to be linked in would change the behavior of toybox.)</p>
  536. <hr /><a name="license" /><h2>License</h2>
  537. <p>Toybox is licensed <a href=license.html>0BSD</a>, which is a public domain
  538. equivalent license approved by <a href=https://spdx.org/licenses/0BSD.html>SPDX</a>. This works like other BSD licenses except that it doesn't
  539. require copying specific license text into the resulting project when
  540. you copy code. (We care about attribution, not ownership, and the internet's
  541. really good at pointing out plagiarism.)</p>
  542. <p>This means toybox usually can't use external code contributions, and must
  543. implement new versions of everything unless the external code's original
  544. author (and any additional contributors) grants permission to relicense.
  545. Just as a GPLv2 project can't incorporate GPLv3 code and a BSD-licensed
  546. project can't incorporate either kind of GPL code, we can't incorporate
  547. most BSD or Apache licensed code without changing our license terms.</p>
  548. <p>The exception to this is code under an existing public domain equivalent
  549. license, such as the xz decompressor or
  550. <a href=https://github.com/mkj/dropbear/blob/master/libtommath/LICENSE>libtommath</a> and <a href=https://github.com/mkj/dropbear/blob/master/libtomcrypt/LICENSE>libtomcrypt</a>.</p>
  551. <hr /><a name="codestyle" /><h2>Coding style</h2>
  552. <p>The real coding style holy wars are over things that don't matter
  553. (whitespace, indentation, curly bracket placement...) and thus have no
  554. obviously correct answer. As in academia, "the fighting is so vicious because
  555. the stakes are so small". That said, being consistent makes the code readable,
  556. so here's how to make toybox code look like other toybox code.</p>
  557. <p>Toybox source uses two spaces per indentation level, and wraps at 80
  558. columns. (Indentation of continuation lines is awkward no matter what
  559. you do, sometimes two spaces looks better, sometimes indenting to the
  560. contents of a parentheses looks better.)</p>
  561. <p>I'm aware this indentation style creeps some people out, so here's
  562. the sed invocation to convert groups of two leading spaces to tabs:</p>
  563. <blockquote><pre>
  564. sed -i ':loop;s/^\( *\) /\1\t/;t loop' filename
  565. </pre></blockquote>
  566. <p>And here's the sed invocation to convert leading tabs to two spaces each:</p>
  567. <blockquote><pre>
  568. sed -i ':loop;s/^\( *\)\t/\1 /;t loop' filename
  569. </pre></blockquote>
  570. <p>There's a space after C flow control statements that look like functions, so
  571. "if (blah)" instead of "if(blah)". (Note that sizeof is actually an
  572. operator, so we don't give it a space for the same reason ++ doesn't get
  573. one. Yeah, it doesn't need the parentheses either, but it gets them.
  574. These rules are mostly to make the code look consistent, and thus easier
  575. to read.) We also put a space around assignment operators (on both sides),
  576. so "int x = 0;".</p>
  577. <p>Blank lines (vertical whitespace) go between thoughts. "We were doing that,
  578. now we're doing this." (Not a hard and fast rule about _where_ it goes,
  579. but there should be some for the same reason writing has paragraph breaks.)</p>
  580. <p>Variable declarations go at the start of blocks, with a blank line between
  581. them and other code. Yes, c99 allowed you to put them anywhere, but they're
  582. harder to find if you do that. If there's a large enough distance between
  583. the declaration and the code using it to make you uncomfortable, maybe the
  584. function's too big, or is there an if statement or something you can
  585. use as an excuse to start a new closer block? Use a longer variable name
  586. that's easier to search for perhaps?</p>
  587. <p>An * binds to a variable name not a type name, so space it that way.
  588. (In C "char *a, b;" and "char* a, b;" mean the same thing: "a" is a pointer
  589. but "b" is not. Spacing it the second way is not how C works.)</p>
  590. <p>We wrap lines at 80 columns. Part of the reason for this I (toybox's
  591. founder Rob) have mediocre eyesight (so tend to increase the font size in
  592. terminal windows and web browsers), and program in a lot of coffee shops
  593. on laptops with a smallish sceen. I'm aware this <a href=http://lkml.iu.edu/hypermail/linux/kernel/2005.3/08168.html>exasperates Linus torvalds</a>
  594. (with his 8-character tab indents where just being in a function eats 8 chars
  595. and 4 more indent levels eats half of an 80 column terminal), but you've
  596. gotta break somewhere and even Linus admits there isn't another obvious
  597. place to do so. (80 columns came from punched cards, which came
  598. from civil war era dollar bill sorting boxes IBM founder Herman Hollerith
  599. bought secondhand when bidding to run the 1890 census. "Totally arbitrary"
  600. plus "100 yeas old" = standard.)</p>
  601. <p>If statements with a single line body go on the same line when the result
  602. fits in 80 columns, on a second line when it doesn't. We usually only use
  603. curly brackets if we need to, either because the body is multiple lines or
  604. because we need to distinguish which if an else binds to. Curly brackets go
  605. on the same line as the test/loop statement. The exception to both cases is
  606. if the test part of an if statement is long enough to split into multiple
  607. lines, then we put the curly bracket on its own line afterwards (so it doesn't
  608. get lost in the multple line variably indented mess), and we put it there
  609. even if it's only grouping one line (because the indentation level is not
  610. providing clear information in that case).</p>
  611. <p>I.E.</p>
  612. <blockquote>
  613. <pre>
  614. if (thingy) thingy;
  615. else thingy;
  616. if (thingy) {
  617. thingy;
  618. thingy;
  619. } else thingy;
  620. if (blah blah blah...
  621. && blah blah blah)
  622. {
  623. thingy;
  624. }
  625. </pre></blockquote>
  626. <p>Gotos are allowed for error handling, and for breaking out of
  627. nested loops. In general, a goto should only jump forward (not back), and
  628. should either jump to the end of an outer loop, or to error handling code
  629. at the end of the function. Goto labels are never indented: they override the
  630. block structure of the file. Putting them at the left edge makes them easy
  631. to spot as overrides to the normal flow of control, which they are.</p>
  632. <p>When there's a shorter way to say something, we tend to do that for
  633. consistency. For example, we tend to say "*blah" instead of "blah[0]" unless
  634. we're referring to more than one element of blah. Similarly, NULL is
  635. really just 0 (and C will automatically typecast 0 to anything, except in
  636. varargs), "if (function() != NULL)" is the same as "if (function())",
  637. "x = (blah == NULL);" is "x = !blah;", and so on.</p>
  638. <p>The goal is to be
  639. concise, not cryptic: if you're worried about the code being hard to
  640. understand, splitting it to multiple steps on multiple lines is
  641. better than a NOP operation like "!= NULL". A common sign of trying too
  642. hard is nesting ? : three levels deep, sometimes if/else and a temporary
  643. variable is just plain easier to read. If you think you need a comment,
  644. you may be right.</p>
  645. <p>Comments are nice, but don't overdo it. Comments should explain _why_,
  646. not how. If the code doesn't make the how part obvious, that's a problem with
  647. the code. Sometimes choosing a better variable name is more revealing than a
  648. comment. Comments on their own line are better than comments on the end of
  649. lines, and they usually have a blank line before them. Most of toybox's
  650. comments are c99 style // single line comments, even when there's more than
  651. one of them. The /* multiline */ style is used at the start for the metadata,
  652. but not so much in the code itself. They don't nest cleanly, are easy to leave
  653. accidentally unterminated, need extra nonfunctional * to look right, and if
  654. you need _that_ much explanation maybe what you really need is a URL citation
  655. linking to a standards document? Long comments can fall out of sync with what
  656. the code is doing. Comments do not get regression tested. There's no such
  657. thing as self-documenting code (if nothing else, code with _no_ comments
  658. is a bit unfriendly to new readers), but "chocolate sauce isn't the answer
  659. to bad cooking" either. Don't use comments as a crutch to explain unclear
  660. code if the code can be fixed.</p>
  661. <!--#include file="footer.html" -->