With advances in graphics cards, new features have been added to allow for increased flexibility in the rendering pipeline at the vertex and fragment level.
Originally, this functionality was achieved by writing shaders in ARB assembly language – a complex and unintuitive task.
GLSL defines a subset of the C preprocessor (CPP), combined with its own special directives for specifying versions and OpenGL extensions.
[19] The GL_ARB_shading_language_include extension[20] (implemented for example in Nvidia drivers[21] on Windows and Linux, and all Mesa 20.0.0[22] drivers on Linux, FreeBSD and Android) implements ability to use #include in source code, allowing easier sharing of code and definitions between many shaders without extra manual pre-processing.
Similar extension GL_GOOGLE_include_directive and GL_GOOGLE_cpp_style_line_directive exist for using GLSL with Vulkan, and are supported in reference SPIR-V compiler (glslang aka glslangValidator).
GLSL shaders themselves are simply a set of strings that are passed to the hardware vendor's driver for compilation from within an application using the OpenGL API's entry points.
GLSL shaders are precompiled before use, or at runtime, into a binary bytecode format called SPIR-V, usually using offline compiler.