Skip to main content

Module include

Module include 

Source
Expand description

#include resolution: where a header is looked for, and what is bundled.

§Search order

#include "name" looks in

  1. the directory of the file the directive is written in — for the macro’s own text that is the directory of the invoking .rs file, and for a header it is the directory that header was found in;
  2. the configured include directories, in the order SearchPaths describes;
  3. 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::name is 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 for some/dir/thing.h from a directive written in some/dir, which neither of the first two steps will find. A bare name is deliberately left out of this step, so that a stdio.h sitting in the working directory never shadows the bundled one;
  4. the bundled headers;
  5. the platform’s own directories — /usr/include and 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 #embed found.
Resolved
A header that was found.
SearchPaths
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_path is 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: 1 for System::Last, first for System::First.
SYSTEM_PATH_ENV_VAR
The environment variable that replaces system_directories’s per-target default, split the way the platform splits PATH.

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 name is one of POSIX_HEADERS.
read_source
Reads the file an include_c99!("…") names.
resolve
Looks a header name up.
resolve_embed
Looks an #embed resource 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.