1# Building Picolibc
2
3Picolibc is designed to be cross-compiled for embedded systems on a
4Linux host using GCC. There is some support for Clang, but that
5doesn't include the built-in multilib support. Picolibc uses the meson
6build system, which is a slightly quirky build system designed to
7replace autotools with a single language.
8
9Picolibc requires meson version 0.50 or newer. If your operating
10system provides an older version, you can get the latest using
11pip. For example, on a Debian or Ubuntu system, you would do:
12
13    $ sudo apt install pip
14    $ pip install meson
15
16On POSIX systems, meson uses the low-level 'ninja' build tool and
17currently requires at least ninja version 1.5. If your operating
18system doesn't provide at least this version, head over to
19[ninja-build.org](https://ninja-build.org) to find out how to
20download and install the latest bits.
21
22## Selecting build options
23
24Use -D<option-name>=<value> on the meson command line to change from
25the default value. Many of these options set configuration values for
26the newlib code base and should match that configuration system. The
27defaults should be reasonable for small embedded systems.
28
29### General build options
30
31These options control some general build configuration values.
32
33| Option                      | Default | Description                                                                          |
34| ------                      | ------- | -----------                                                                          |
35| fast-strcmp                 | true    | Always optimize strcmp for performance (to make Dhrystone happy)                     |
36| have-alias-attribute        | auto    | Compiler supports __alias__ attribute (default autodetected)                         |
37| have-format-attribute       | auto    | Compiler supports __format__ attribute (default autodetected)                        |
38| multilib                    | true    | Build every multilib configuration supported by the compiler                         |
39| multilib-list               | <empty> | If non-empty, the set of multilib configurations to compile for                      |
40| native-tests                | false   | Build tests against native libc (used to validate tests)                             |
41| picolib                     | true    | Include picolib bits for tls and sbrk support                                        |
42| picocrt                     | true    | Build crt0.o (C startup function)                                                    |
43| picocrt-lib                 | true    | Also wrap crt0.o into a library -lcrt0, which is easier to find via the library path |
44| semihost                    | true    | Build the semihost library (libsemihost.a)                                           |
45| fake-semihost               | false   | Create a fake semihost library to allow tests to link                                |
46| specsdir                    | auto    | Where to install the .specs file (default is in the GCC directory). <br> If set to `none`, then picolibc.specs will not be installed at all.|
47| sysroot-install             | false   | Install in GCC sysroot location (requires sysroot in GCC)                            |
48| tests                       | false   | Enable tests                                                                         |
49| tinystdio                   | true    | Use tiny stdio from avr libc                                                         |
50
51### Options applying to both legacy stdio and tinystdio
52
53These options extend support in printf and scanf for additional
54types and formats.
55
56| Option                      | Default | Description                                                                          |
57| ------                      | ------- | -----------                                                                          |
58| io-c99-formats              | true    | Enable C99 support in IO functions like printf/scanf                                 |
59| io-long-long                | false   | Enable long long type support in IO functions like printf/scanf. For tiny-stdio, this only affects the integer-only versions, the full version always includes long long support. |
60| io-pos-args                 | false   | Enable printf-family positional arg support. For tiny-stdio, this only affects the integer-only versions, the full version always includes positional argument support. |
61| io-long-double              | false   | Enable long double support in printf/scanf.                                          |
62
63
64`long long` support is always enabled for the tinystdio full
65printf/scanf modes, the `io-long-long` option adds them to the limited
66(float and integer) versions, as well as to the original newlib stdio
67bits.
68
69### Options when using tinystdio bits
70
71These options apply when tinystdio is enabled, which is the
72default. For stdin/stdout/stderr, the application will need to provide
73`stdin`, `stdout` and `stderr`, which are three pointers to FILE
74structures (which can all reference a single shared FILE structure,
75and which can be aliases to the same underlying global pointer).
76
77Note that while posix-io support is enabled by default, using it will
78require that the underlying system offer the required functions. POSIX
79console support offers built-in `stdin`, `stdout` and `stderr`
80definitions which use the same POSIX I/O functions.
81
82| Option                      | Default | Description                                                                          |
83| ------                      | ------- | -----------                                                                          |
84| atomic-ungetc               | true    | Make getc/ungetc re-entrant using atomic operations                                  |
85| io-float-exact              | true    | Provide round-trip support in float/string conversions                               |
86| posix-io                    | true    | Provide fopen/fdopen using POSIX I/O (requires open, close, read, write, lseek)      |
87| posix-console               | false   | Use POSIX I/O for stdin/stdout/stderr                                                |
88| format-default              | double  | Sets the default printf/scanf style ('double', 'float' or 'integer')                 |
89| printf-aliases              | true    | Support link-time printf aliases to set the default printf/scanf variant             |
90| io-percent-b                | false   | Support the %b as proposed in the upcoming C standard                                |
91| printf-small-ultoa          | false   | Avoid soft division routine during integer binary to decimal conversion in printf    |
92| minimal-io-long-long        | false   | Support long long integers in the minimal printf and scanf variants                  |
93| fast-bufio                  | false   | Improve performance of some I/O operations when using bufio                          |
94
95
96### Options when using legacy stdio bits
97
98Normally, Picolibc is built with the small stdio library adapted from
99avrlibc (tinystdio=true). It still has the original newlib
100stdio bits and those still work (tinystdio=false), but depend
101on POSIX I/O functions from the underlying system, and perform many
102malloc calls at runtime. These options are relevant only in that
103configuration
104
105| Option                      | Default | Description                                                                          |
106| ------                      | ------- | -----------                                                                          |
107| newlib-elix-level           |  0      | Extends stdio API based on level                                                     |
108| newlib-fseek-optimization   | false   | Enable fseek optimization                                                            |
109| newlib-fvwrite-in-streamio  | false   | Enable iov in streamio                                                               |
110| newlib-global-stdio-streams | false   | Enable global stdio streams                                                          |
111| newlib-have-fcntl           | false   | System has fcntl function available                                                  |
112| newlib-io-float             | false   | Enable printf/scanf family float support                                             |
113| newlib-io-long-double       | false   | Enable long double type support in IO functions printf/scanf                         |
114| newlib-nano-formatted-io    | false   | Use nano version formatted IO                                                        |
115| newlib-reent-small          | false   | Enable small reentrant struct support                                                |
116| newlib-stdio64              | true    | Include 64-bit APIs                                                                  |
117| newlib-unbuf-stream-opt     | false   | Enable unbuffered stream optimization in streamio                                    |
118| newlib-wide-orient          | false   | Turn off wide orientation in streamio                                                |
119
120### Internationalization options
121
122These options control which character sets are supported by iconv.
123
124| Option                      | Default | Description                                                                          |
125| ------                      | ------- | -----------                                                                          |
126| newlib-iconv-encodings      | <empty> | Comma-separated list of iconv encodings to be built-in (default all supported). <br> Set to `none` to disable all encodings. |
127| newlib-iconv-from-encodings | <empty> | Comma-separated list of "from" iconv encodings to be built-in (default iconv-encodings) |
128| newlib-iconv-to-encodings   | <empty> | Comma-separated list of "to" iconv encodings to be built-in (default iconv-encodings) |
129| newlib-iconv-external-ccs   | false   | Use file system to store iconv tables. Requires fopen. (default built-in to memory)  |
130| newlib-iconv-dir            | libdir/locale | Directory to install external CCS files. Only used with newlib-iconv-external-ccs=true |
131| newlib-iconv-runtime-dir    | newlib-iconv-dir | Directory to read external CCS files from at runtime. |
132
133These options control how much Locale support is included in the
134library. By default, picolibc only supports the 'C' locale.
135
136| Option                      | Default | Description                                                                          |
137| ------                      | ------- | -----------                                                                          |
138| newlib-locale-info          | false   | Enable locale support                                                                |
139| newlib-locale-info-extended | false   | Enable even more locale support                                                      |
140| newlib-mb                   | false   | Enable multibyte support                                                             |
141
142### Startup/shutdown options
143
144These control how much support picolibc includes for calling functions
145at startup and shutdown times.
146
147| Option                      | Default | Description                                                                          |
148| ------                      | ------- | -----------                                                                          |
149| lite-exit                   | true    | Enable lightweight exit                                                             |
150| newlib-atexit-dynamic-alloc | false   | Enable dynamic allocation of atexit entries                                          |
151| newlib-global-atexit        | false   | Enable atexit data structure as global, instead of in TLS. <br> If `thread-local-storage` == false, then the atexit data structure is always global. |
152| newlib-initfini             | true    | Support _init() and _fini() functions in picocrt                                     |
153| newlib-initfini-array       | true    | Use .init_array and .fini_array sections in picocrt                                  |
154| newlib-register-fini        | false   | Enable finalization function registration using atexit                               |
155| crt-runtime-size            | false   | Compute .data/.bss sizes at runtime rather than linktime. <br> This option exists for targets where the linker can't handle a symbol that is the difference between two other symbols, e.g. m68k.|
156
157### Thread local storage support
158
159By default, Picolibc can uses native TLS support as provided by the
160compiler, this allows re-entrancy into the library if the run-time
161environment supports that. A TLS model is specified only when TLS is
162enabled. The default TLS model is local-exec.
163
164As a separate option, you can make `errno` not use TLS if necessary.
165
166| Option                      | Default | Description                                                                          |
167| ------                      | ------- | -----------                                                                          |
168| thread-local-storage        | auto    | Use TLS for global variables. Default is automatic based on compiler support         |
169| tls-model                   | local-exec | Select TLS model (global-dynamic, local-dynamic, initial-exec or local-exec)      |
170| newlib-global-errno         | false   | Use single global errno even when thread-local-storage=true                          |
171| errno-function              | <empty> | If set, names a function which returns the address of errno. 'auto' will try to auto-detect. |
172
173### Malloc option
174
175Picolibc offers two malloc implementations, the larger version offers
176better performance on large memory systems and for applications doing
177a lot of variable-sized allocations and deallocations. The smaller,
178default, implementation works best when applications perform few,
179persistent allocations.
180
181| Option                      | Default | Description                                                                          |
182| ------                      | ------- | -----------                                                                          |
183| newlib-nano-malloc          | true    | Use small-footprint nano-malloc implementation                                       |
184
185### Locking support
186
187There are some functions in picolibc that use global data that needs
188protecting when accessed by multiple threads. The largest set of these
189are the legacy stdio code, but there are other functions that can use
190locking, e.g. when newlib-global-atexit is enabled, calls to atexit
191need to lock the shared global data structure if they may be called
192from multiple threads at the same time. By default, these are enabled
193and use the retargetable API defined in [locking.md](locking.md).
194
195| Option                      | Default | Description                                                                          |
196| ------                      | ------- | -----------                                                                          |
197| newlib-retargetable-locking | true    | Allow locking routines to be retargeted at link time                                 |
198| newlib-multithread          | true    | Enable support for multiple threads                                                  |
199
200
201### Legacy newlib options
202
203These either have no effect or should not be enabled in normal use of
204picolibc, they're left in the library to help users porting from
205newlib environments.
206
207| Option                      | Default | Description                                                                          |
208| ------                      | ------- | -----------                                                                          |
209| newlib-long-time_t          | false   | Define time_t to long instead of using a 64-bit type                                 |
210| newlib-supplied-syscalls    | false   | Enable newlib supplied syscalls (obsolete)                                           |
211| newlib-reentrant-syscalls-provided| false| Underlying system provides reentrant syscall API                                  |
212| newlib-missing-syscall-names| false   | Underlying system provides syscall names without leading underscore                  |
213
214### Math library options
215
216There are two versions of many libm functions, old ones from SunPro
217and new ones from ARM. The new ones are generally faster for targets
218with hardware double support, except that the new float-valued
219functions use double-precision computations. On sytems without
220hardware double support, that's going to pull in soft double
221code. Measurements show the old routines are generally more accurate,
222which is why they are enabled by default.
223
224POSIX requires many of the math functions to set errno when exceptions
225occur; disabling that makes them only support fenv() exception
226reporting, which is what IEEE floating point and ANSI C standards
227require.
228
229| Option                      | Default | Description                                             |
230| ------                      | ------- | -----------                                             |
231| newlib-obsolete-math        | true    | Use old code for both float and double valued functions |
232| newlib-obsolete-math-float  | auto    | Use old code for float-valued functions                 |
233| newlib-obsolete-math-double | auto    | Use old code for double-valued functions                |
234| want-math-errno             | false   | Set errno when exceptions occur                         |
235
236newlib-obsolete-math provides the default value for the
237newlib-obsolete-math-float and newlib-obsolete-math-double parameters;
238those control the compilation of the individual fucntions.
239
240## Building for embedded RISC-V and ARM systems
241
242Meson sticks all of the cross-compilation build configuration bits in
243a separate configuration file. There are a bunch of things you need to
244set, which the build system really shouldn't care about. Example
245configuration settings for RISC-V processors are in
246cross-riscv64-unknown-elf.txt:
247
248    [binaries]
249    c = 'riscv64-unknown-elf-gcc'
250    ar = 'riscv64-unknown-elf-ar'
251    as = 'riscv64-unknown-elf-as'
252    ld = 'riscv64-unknown-elf-ld'
253    strip = 'riscv64-unknown-elf-strip'
254
255    [host_machine]
256    system = 'unknown'
257    cpu_family = 'riscv'
258    cpu = 'riscv'
259    endian = 'little'
260
261    [properties]
262    c_args = [ '-nostdlib', '-msave-restore', '-fno-common' ]
263    # default multilib is 64 bit
264    c_args_ = [ '-mcmodel=medany' ]
265    needs_exe_wrapper = true
266    skip_sanity_check = true
267
268Settings for ARM processors are in cross-arm-none-eabi.txt:
269
270    [binaries]
271    c = 'arm-none-eabi-gcc'
272    ar = 'arm-none-eabi-ar'
273    as = 'arm-none-eabi-as'
274    ld = 'arm-none-eabi-ld'
275    strip = 'arm-none-eabi-strip'
276
277    [host_machine]
278    system = 'none'
279    cpu_family = 'arm'
280    cpu = 'arm'
281    endian = 'little'
282
283    [properties]
284    c_args = [ '-nostdlib', '-fno-common' ]
285    needs_exe_wrapper = true
286    skip_sanity_check = true
287
288If those programs aren't in your path, you can edit the file to point
289wherever they may be.
290
291### Auto-detecting the compiler multi-lib configurations
292
293The PicoLibc configuration detects the processor configurations
294supported by the compiler using the `--print-multi-lib` command-line option:
295
296    $ riscv64-unknown-elf-gcc --print-multi-lib
297    .;
298    rv32e/ilp32e;@march=rv32e@mabi=ilp32e
299    rv32ea/ilp32e;@march=rv32ea@mabi=ilp32e
300    rv32em/ilp32e;@march=rv32em@mabi=ilp32e
301    rv32eac/ilp32e;@march=rv32eac@mabi=ilp32e
302    rv32emac/ilp32e;@march=rv32emac@mabi=ilp32e
303    rv32i/ilp32;@march=rv32i@mabi=ilp32
304    rv32if/ilp32f;@march=rv32if@mabi=ilp32f
305    rv32ifd/ilp32d;@march=rv32ifd@mabi=ilp32d
306    rv32ia/ilp32;@march=rv32ia@mabi=ilp32
307    rv32iaf/ilp32f;@march=rv32iaf@mabi=ilp32f
308    rv32imaf/ilp32f;@march=rv32imaf@mabi=ilp32f
309    rv32iafd/ilp32d;@march=rv32iafd@mabi=ilp32d
310    rv32im/ilp32;@march=rv32im@mabi=ilp32
311    rv32imf/ilp32f;@march=rv32imf@mabi=ilp32f
312    rv32imfc/ilp32f;@march=rv32imfc@mabi=ilp32f
313    rv32imfd/ilp32d;@march=rv32imfd@mabi=ilp32d
314    rv32iac/ilp32;@march=rv32iac@mabi=ilp32
315    rv32imac/ilp32;@march=rv32imac@mabi=ilp32
316    rv32imafc/ilp32f;@march=rv32imafc@mabi=ilp32f
317    rv32imafdc/ilp32d;@march=rv32imafdc@mabi=ilp32d
318    rv64i/lp64;@march=rv64i@mabi=lp64
319    rv64if/lp64f;@march=rv64if@mabi=lp64f
320    rv64ifd/lp64d;@march=rv64ifd@mabi=lp64d
321    rv64ia/lp64;@march=rv64ia@mabi=lp64
322    rv64iaf/lp64f;@march=rv64iaf@mabi=lp64f
323    rv64imaf/lp64f;@march=rv64imaf@mabi=lp64f
324    rv64iafd/lp64d;@march=rv64iafd@mabi=lp64d
325    rv64im/lp64;@march=rv64im@mabi=lp64
326    rv64imf/lp64f;@march=rv64imf@mabi=lp64f
327    rv64imfc/lp64f;@march=rv64imfc@mabi=lp64f
328    rv64imfd/lp64d;@march=rv64imfd@mabi=lp64d
329    rv64iac/lp64;@march=rv64iac@mabi=lp64
330    rv64imac/lp64;@march=rv64imac@mabi=lp64
331    rv64imafc/lp64f;@march=rv64imafc@mabi=lp64f
332    rv64imafdc/lp64d;@march=rv64imafdc@mabi=lp64d
333
334    $ arm-none-eabi-gcc --print-multi-lib
335    .;
336    thumb;@mthumb
337    hard;@mfloat-abi=hard
338    thumb/v6-m;@mthumb@march=armv6s-m
339    thumb/v7-m;@mthumb@march=armv7-m
340    thumb/v7e-m;@mthumb@march=armv7e-m
341    thumb/v7-ar;@mthumb@march=armv7
342    thumb/v8-m.base;@mthumb@march=armv8-m.base
343    thumb/v8-m.main;@mthumb@march=armv8-m.main
344    thumb/v7e-m/fpv4-sp/softfp;@mthumb@march=armv7e-m@mfpu=fpv4-sp-d16@mfloat-abi=softfp
345    thumb/v7e-m/fpv4-sp/hard;@mthumb@march=armv7e-m@mfpu=fpv4-sp-d16@mfloat-abi=hard
346    thumb/v7e-m/fpv5/softfp;@mthumb@march=armv7e-m@mfpu=fpv5-d16@mfloat-abi=softfp
347    thumb/v7e-m/fpv5/hard;@mthumb@march=armv7e-m@mfpu=fpv5-d16@mfloat-abi=hard
348    thumb/v7-ar/fpv3/softfp;@mthumb@march=armv7@mfpu=vfpv3-d16@mfloat-abi=softfp
349    thumb/v7-ar/fpv3/hard;@mthumb@march=armv7@mfpu=vfpv3-d16@mfloat-abi=hard
350    thumb/v7-ar/fpv3/hard/be;@mthumb@march=armv7@mfpu=vfpv3-d16@mfloat-abi=hard@mbig-endian
351    thumb/v8-m.main/fpv5-sp/softfp;@mthumb@march=armv8-m.main@mfpu=fpv5-sp-d16@mfloat-abi=softfp
352    thumb/v8-m.main/fpv5-sp/hard;@mthumb@march=armv8-m.main@mfpu=fpv5-sp-d16@mfloat-abi=hard
353    thumb/v8-m.main/fpv5/softfp;@mthumb@march=armv8-m.main@mfpu=fpv5-d16@mfloat-abi=softfp
354    thumb/v8-m.main/fpv5/hard;@mthumb@march=armv8-m.main@mfpu=fpv5-d16@mfloat-abi=hard
355
356On RISC-V, PicoLibc is compiled 36 times, while on ARM, the library is
357compiled 20 times with the specified compiler options (replace the
358'@'s with '-' to see what they will be).
359
360### Running meson
361
362Because Picolibc targets smaller systems like the SiFive FE310 or ARM
363Cortex-M0 parts with only a few kB of RAM and flash, the default
364values for all of the configuration options are designed to minimize
365the library code size. Here's the
366[do-riscv-configure](../scripts/do-riscv-configure) script from the repository
367that configures the library for small RISC-V systems:
368
369    #!/bin/sh
370    ARCH=riscv64-unknown-elf
371    DIR=`dirname $0`
372    meson "$DIR" \
373	    -Dincludedir=picolibc/$ARCH/include \
374	    -Dlibdir=picolibc/$ARCH/lib \
375	    --cross-file "$DIR"/cross-$ARCH.txt \
376	    "$@"
377
378This script is designed to be run from a build directory, so you'd do:
379
380    $ mkdir build-riscv64-unknown-elf
381    $ cd build-riscv64-unknown-elf
382    $ ../scripts/do-riscv-configure
383
384You can select the installation directory by passing it to the meson script:
385
386    $ ../scripts/do-riscv-configure -Dprefix=/path/to/install/dir/
387
388### Compiling
389
390Once configured, you can compile the libraries with
391
392    $ ninja
393    ...
394    $ ninja install
395    ...
396    $
397