Expand description
#include resolution: where a header is looked for, and what is bundled.
§Search order
#include "name" looks in
- the directory of the file the directive is written in — for the macro’s
own text that is the directory of the invoking
.rsfile, and for a header it is the directory that header was found in; - the configured include directories, in the order
SearchPathsdescribes; - the working directory, but only when the name is a path — when it
holds a directory separator. That is what makes
#include __FILE__work:Resolved::nameis written relative to the working directory wherever it can be (a diagnostic naming an absolute path is a diagnostic that differs between two machines), so a header that includes itself by__FILE__is asking forsome/dir/thing.hfrom a directive written insome/dir, which neither of the first two steps will find. A bare name is deliberately left out of this step, so that astdio.hsitting in the working directory never shadows the bundled one; - the bundled headers;
- the platform’s own directories —
/usr/includeand friends — but only when the switch is on.
#include <name> skips steps 1 and 3. A name that is absolute is used as
it stands.
§The platform’s own directories
Step 5 is off by default, and everything above it is enough for a
self-contained, target-model-portable unit. A real <stdio.h> is not
plain C: glibc’s is a thicket of __attribute__, __extension__,
__asm__ renaming and compiler builtins, and its layouts are the host’s
rather than the target model’s. So cinrs ships its own
small, plain-C99 declarations of the standard library: they declare exactly
what the platform’s real library exports, the linker binds the calls to the
real implementation, and the C that uses them is ordinary C.
The bundled set is ISO C, plus what only the compiler can provide.
Everything in BUNDLED is a header the C standard describes, with two
groups of exceptions: <alloca.h>, because alloca is implemented by this
crate rather than by any library, and the Intel intrinsics headers —
<immintrin.h>, <xmmintrin.h> and the rest — because __m128i and
_mm_add_epi32 are the compiler’s too. Neither has a library behind it, so
the platform’s copy would have nothing to add and everything to break: a
real <immintrin.h> is a thicket of __attribute__((vector_size)) and
__builtin_ia32_*, and this one is prototypes that
crate::x86 maps onto core::arch.
POSIX is the platform’s: <unistd.h>, <fcntl.h>, <sys/types.h>,
<pthread.h>, <sys/stat.h> and the rest come from the platform’s own
directories, complete and consistent with each other, once the switch below
is on. (Up to 0.1.0 four small POSIX headers were bundled too; they were
incomplete — no access, no fsync, no struct flock — and a program that
turned the platform on still got the bundled ones, which is the opposite of
what it asked for.)
What the bundled set cannot give is POSIX, and the things whose layout
only the platform knows — struct stat, DIR, pthread_mutex_t, the real
FILE — so a program that needs those turns the switch on with
#pragma cinrs system_include (or CINRS_SYSTEM_INCLUDE=1 in the
environment, which is the crate-wide default the pragma overrides). With
System::Last the bundled headers still win, and only a name they do not
carry reaches the platform; with System::First the platform’s copy of
every header wins, which is what makes FILE the real struct _IO_FILE.
The bundled ISO headers guard the types and macros a platform header would
also define with that platform’s own guard macros, so that the two sets can
be mixed in System::Last mode: see the comments in include/time.h.
The directories searched are SYSTEM_PATH_ENV_VAR when it is set, and
otherwise system_directories’s per-target default. The compiler’s own
private directories are never among them: GCC’s and Clang’s
.../include/{limits,stdint,stddef,stdarg}.h chain to the next header of
the same name with #include_next and expect their own compiler’s
builtins, and every one of those headers is bundled here anyway.
Nothing found under step 5 is tracked for rebuilds: a system header is part
of the machine rather than of the crate, and include_str!-ing
/usr/include/stdio.h into the build would make every unit rebuild when the
libc package is upgraded, which is not what the file identifies.
Structs§
- Embedded
- A resource
#embedfound. - Resolved
- A header that was found.
- Search
Paths - The include directories a unit searches, in the order it searches them.
Enums§
- Entry
- One place a search looks, in the order it looks.
- Error
- Why a header could not be included.
- Form
- How the header name was spelled.
- Origin
- The directory a file’s own
#include "…"searches first. - System
- Whether the platform’s own include directories are searched, and where in the order they go.
Constants§
- BUNDLED
- The bundled standard headers, as
(name, text)pairs. - BUNDLED_
DIR - The directory the bundled headers appear to live in.
- ENV_VAR
- The environment variable holding a global list of include directories.
- MANIFEST_
DIR_ VAR - The environment variable Cargo sets to the package’s own directory, which
is what a relative
#pragma cinrs include_pathis resolved against. - POSIX_
HEADERS - The POSIX headers a program is likely to reach for, none of which is bundled.
- SYSTEM_
ENV_ VAR - The environment variable that turns the platform’s directories on for a
whole crate:
1forSystem::Last,firstforSystem::First. - SYSTEM_
PATH_ ENV_ VAR - The environment variable that replaces
system_directories’s per-target default, split the way the platform splitsPATH.
Functions§
- bundled
- The text of a bundled header, by name.
- bundled_
name - The display name a bundled header is known by:
<cinrs>/stdio.h. - display_
path - How a path is written in a diagnostic.
- is_
posix_ header - Whether
nameis one ofPOSIX_HEADERS. - read_
source - Reads the file an
include_c99!("…")names. - resolve
- Looks a header name up.
- resolve_
embed - Looks an
#embedresource up (C23 6.10.3). - resolve_
next #include_next <name>: the same search, taken up again at the entry after the one the file writing the directive was found under.- system_
directories - The platform’s own include directories for
target, when nothing named them.