Skip to content

/flags/c/gcc-i-include-path

gcc -I dir: add a header search path (fix "No such file or directory" for #include)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
C
command
gcc
flag
-I dir
default
the directory of the current file (for #include "...") and the system include directories

gcc -Iinclude main.c adds the directory include to the list of places the preprocessor searches for header files, so #include <mylib/math.h> finds include/mylib/math.h. Directories given with -I are searched before the standard system directories, in the order they appear on the command line. Without it, a header that is not next to the source file or in a system directory fails with fatal error: mylib/math.h: No such file or directory (GCC) or fatal error: 'mylib/math.h' file not found (Clang).

Without and with -I

The example uses Clang 20 from the Zig 0.15.1 toolchain (installed from PyPI with uv); cc below is that compiler, and GCC accepts the same options:

bash
cc() { uv run -q --no-project --python 3.13 --with ziglang==0.15.1 python -m ziglang cc -fno-color-diagnostics "$@"; }
mkdir -p include/mylib src
cat > include/mylib/math.h <<'EOF'
#pragma once
int add(int a, int b);
EOF
cat > src/math.c <<'EOF'
#include <mylib/math.h>
int add(int a, int b) { return a + b; }
EOF
cat > src/main.c <<'EOF'
#include <stdio.h>
#include <mylib/math.h>
int main(void) { printf("2 + 3 = %d\n", add(2, 3)); return 0; }
EOF
echo "== without -I"
cc src/main.c src/math.c -o app1; echo "exit: $?"
echo "== with -Iinclude"
cc -Iinclude src/main.c src/math.c -o app2 && ./app2

Output

== without -I
src/math.c:1:10: fatal error: 'mylib/math.h' file not found
    1 | #include <mylib/math.h>
      |          ^~~~~~~~~~~~~~
1 error generated.
src/main.c:2:10: fatal error: 'mylib/math.h' file not found
    2 | #include <mylib/math.h>
      |          ^~~~~~~~~~~~~~
1 error generated.
exit: 1
== with -Iinclude
2 + 3 = 5

Each source file that includes the header fails on its own without -I. With -Iinclude both compile, link and run. The path is relative to the directory where the compiler is started, not to the source file.

Search order

Order#include "file.h"#include <file.h>
1Directory of the file that contains the #include-
2Directories from -iquote, left to right-
3Directories from -I, left to rightDirectories from -I, left to right
4Directories from -isystem, then the standard system directoriesSame
5Directories from -idirafterSame

Related options: -iquote dir (only for the quoted form), -isystem dir (treated like a system directory, so warnings from those headers are suppressed), -idirafter dir (searched last), -nostdinc (ignore the standard directories), and the environment variables CPATH and C_INCLUDE_PATH, which act like -I and -isystem.

Typical uses

bash
gcc -Iinclude -Ithird_party/json/include -c src/main.c -o build/main.o
gcc -I"$(brew --prefix openssl)/include" -c tls.c                      # Homebrew libraries on macOS
gcc $(pkg-config --cflags libcurl) -c net.c $(pkg-config --libs libcurl) # let pkg-config supply -I and -l

pkg-config --cflags prints the right -I (and -D) options for installed libraries; prefer it over hard-coded paths. In CMake, target_include_directories(app PRIVATE include) generates -I for you.

Pitfalls

  • -I fixes compile-time header lookup only. If the header is found but the function lives in a library that is not linked, the error moves to the linker as undefined reference; add the source file or -lname (and -L dir).
  • Do not add -I/usr/include or other system directories: it changes the search order of system headers and can break #include_next in the C library.
  • Two directories with a header of the same name: the first -I wins, which can silently pick an old copy. Prefer prefixed includes such as <mylib/math.h>, as in the example.
  • For multi-file builds and object files, see compile multiple C files.

FAQ

What is the difference between -I and -L?

-I adds a directory for header files, used by the preprocessor for #include. -L adds a directory for libraries, used by the linker together with -lname. A missing -I gives a 'file not found' error at compile time; a missing -L or -l gives undefined reference errors at link time.

Should I use #include "file.h" or #include <file.h>?

Quotes for headers of your own project: they are searched first in the directory of the including file, then in the -iquote and -I paths. Angle brackets for system and library headers: they skip the current directory and search the -I paths, then the system directories.

How do I see where the compiler searches for headers?

Run gcc -v -E -x c /dev/null (or clang the same way). The output lists the #include "..." and #include <...> search directories in order, including those added with -I.

Sources