Skip to main content

SearchPath

Struct SearchPath 

Source
pub struct SearchPath { /* private fields */ }
Expand description

The directories a header is looked for in, in order.

GCC’s order, because a different one produces header shadowing bugs that are miserable to diagnose: -iquote first and only for a quoted include, then -I, then -isystem, then the configured system directories, then -idirafter. The directory of the including file comes before all of it for a quoted include, and it is not part of the numbered list because #include_next must not be able to land back on it.

Implementations§

Source§

impl SearchPath

Source

pub fn new() -> SearchPath

An empty search path.

Source

pub fn push_quote(&mut self, dir: impl Into<PathBuf>)

Adds a -iquote directory, searched only for a quoted include.

Source

pub fn push_bracket(&mut self, dir: impl Into<PathBuf>)

Adds a -I directory.

Source

pub fn push_system(&mut self, dir: impl Into<PathBuf>)

Adds a -isystem directory, or one of the target’s configured system directories.

Source

pub fn push_after(&mut self, dir: impl Into<PathBuf>)

Adds a -idirafter directory, which is searched after everything else.

Source

pub fn split_quote_chain(&mut self)

Makes every directory added so far reachable only by a quoted include, which is -I-.

The flag GCC deprecated in favour of -iquote and still supports, because a build system old enough to be worth compiling is old enough to pass it. It does two things at once. The -I directories written before it move into the quoted chain, so #include <x.h> stops seeing them, and the directory of the including file comes off the front of that chain, so #include "x.h" stops looking next to the file that wrote it.

The second half is the reason the flag was worth having and the reason it was worth dropping. It is the only way to say that a quoted include means a directory the command line named rather than whatever happens to sit beside the source, which is what a project with two headers of the same name in two directories needs. It is also a global answer to a question every include asks separately, which is why -iquote replaced it.

A -iquote directory given before this stays in the quoted chain, and lands after the -I directories that just joined it. That is GCC’s order and not an accident of the implementation: GCC holds -iquote back until every -I and -I- has been dealt with, so a -iquote is always later in the chain than an -I whatever order they were written.

Source

pub fn searches_current_dir(&self) -> bool

Whether the directory of the including file is searched for a quoted include.

False once -I- has been given. A caller that has a directory to offer still passes it, and this is where it is refused, so that the rule lives with the search path rather than at every call site that knows where a file came from.

Source

pub fn remove_duplicates(&mut self)

Drops the directories that are already on the path, the way GCC does.

A duplicate is not a harmless extra entry that costs one failed open. It changes what #include_next means, which is defined as continuing past the directory the current file came from: a header found in the first /usr/include writes #include_next <stdint.h> meaning “the one below me” and finds itself in the second, and a header set that ends in a fixed point of its own is one that includes itself forever or answers __has_include_next yes where the compiler it was written for said no. It shows up as soon as somebody passes the system directories on the command line, which the compat harness does deliberately and a build system does by accident.

A -I that names a system directory loses to the system entry rather than the other way round, and that is GCC’s rule and is documented as one: keeping the earlier one would move a system directory up the order and take the system treatment off the headers in it, so the -I is the one that goes.

Two names for one directory are two directories here, where GCC compares the device and the inode and sees through a symlink. That wants a file system that can answer the question and this one deliberately only reads.

Source

pub fn dirs(&self) -> &[Dir]

Every directory, in search order.

Source

pub fn start(&self, form: IncludeForm) -> usize

The first entry an include of this form looks at.

An angled include skips the -iquote directories, which is the only difference between the two chains once the including file’s own directory is out of the way.

Source

pub fn resolve( &self, fs: &dyn FileSystem, name: &str, form: IncludeForm, relative_to: Option<&Path>, from: usize, ) -> Option<Found>

Finds name, starting at entry from of the search path.

relative_to is the directory of the file doing the including, tried first for a quoted include and ignored otherwise. Pass None for an #include_next, which is defined as continuing past the directory the current file was found in and so must not look next to it again. It is also ignored after SearchPath::split_quote_chain, which is what -I- asks for.

An absolute name is opened directly and the search path is not consulted, which is what every C compiler does and what a generated header with an absolute path needs.

Source

pub fn tried( &self, name: &str, form: IncludeForm, relative_to: Option<&Path>, from: usize, ) -> Vec<PathBuf>

The directories a failed SearchPath::resolve with the same arguments looked in.

spec/05-preprocessor.md section 5.7 makes printing this the required behaviour for a failed include, because “file not found” without the list of places that were tried is the diagnostic that wastes the most time in this part of the compiler.

Trait Implementations§

Source§

impl Clone for SearchPath

Source§

fn clone(&self) -> SearchPath

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for SearchPath

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for SearchPath

Source§

fn default() -> SearchPath

Returns the “default value” for a type. Read more
Source§

impl Eq for SearchPath

Source§

impl PartialEq for SearchPath

Source§

fn eq(&self, other: &SearchPath) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for SearchPath

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.