Dealing with GL reflection
opengl has several methods that together let you reflect the shader IO.

However it is much simpler if the shader IO is uniform across all your shaders. IOW have a set of default bindings/locations for everything. Then you only need some meta data for each shader where you deviate from those defaults for some reason.

You then only need to query that the binding exists to see whether you need to provide the data. This has the added bonus that if an input gets optimized out you'll not waste time giving data it doesn't need.