Search code examples
cgccmsys2

How do I use an external library with gcc?


I am attempting to compile this code:

#include <GLFW/glfw3.h>

int main() {
    glfwInit();
    glfwTerminate();

    return 0;
}

Using this command in MSYS2 on Windows 10:

gcc -Wall runVulkan.c -o runVulkan

as well as this:

gcc -Wall -Llibs/glfw runVulkan.c -o runVulkan

libs/glfw is where I downloaded the library to.

For some reason I keep getting this:

runVulkan.c:1:10: fatal error: GLFW/glfw3.h: No such file or directory
    1 | #include <GLFW/glfw3.h>
      |          ^~~~~~~~~~~~~~
compilation terminated.

It seems like I'm getting something very basic wrong.

I'm just getting started with C, I'm trying to import Vulkan libraries.


Solution

  • #include are just headers, for declarations. gcc, as any compilers, needs to know where those .h should be searched.

    You can specify that with -I option (or C_INCLUDE_PATH environment variable).

    You'll also need -L option, this times to provide the library itself (.h does not contain the library. Just declarations that the compiler needs to know how to compile codes that use the library function's and types).

    -L option tells the compiler where to search for libraries.

    But here, you haven't specify any libraries (just headers. And I know that it seems logical that they go together. But strictly speaking, there is no way to guess from #include <GLFW/glfw3.h> which library that file contain headers for (that is not just theory. In practice, for example, the well known libc declarations are in many different headers)

    So, you will also have to specify a -l option. In your case -lglfw.

    This seems over complicated, because in your case you compile and like in a single command (goes from .c to executable directly). But that are two different operations done in one command.

    Creation of an executable from .c code source is done in two stage.

    Compilation itself. Creating .o from .c (many .c for big codes), so many compilation commands. Using command such as

    gcc -I /path/where/to/find/headers -c mycode.c -o mycode.o
    

    Those are not related to the library. So no -l (and therefore no -L) for that. What is compiled is your code, so just your code is needed at this stage. Plus the header files, because your code refers to unknown function and types, and the compiler needs to know, not their code, but at least declarations that they really exist, and what are the types expected and returned by the functions is the headers files.

    Then, once all the .o are compiled, you need to put together all compiled code, yours (the .o) and the libraries (which are somehow a sort of .zip of .o) to create an executable. That is called linking. And is done with commands like

    gcc -o myexec mycode1.o mycode2.o -L /path/where/to/search/for/libraries -lrary
    

    (-lbla is a compact way to include /path/where/to/search/for/libraries/libbla.so or /path/where/to/search/for/libraries/libbla.a)

    At this stage, you no longer need -I or anything related to headers. The code is already compiled, headers has no role left. But you need everything needed to find the compile code of the libraries.

    So, tl;dr

    • At compilation stage (the stage that raises the error you have for now), you need -I option so that the compiler knows where to find GLFW/glfw3.h
    • But that alone wont avoid you the next error that will occur at linking stage. At this stage, you need -lglfw to specify that you want to use that library, and a -L option so that the compiler knows where to find a libglfw.so