This is not easy and will be significant work. You first want to reach a stage where you can pick any set of files and they either compile or they don’t, but if they compile, they will give the same result. Why wouldn’t they? For example because header files #define things that other header files or source files use.
Say your source file says
#ifndef PI
#define PI 3.15
#endif
If you stop including a header file with a precise definition of PI and nothing else, your program is suddenly very inaccurate.
So you look for things defined in header files and where they are used. The source file here would be changed, the PI madness removed and the header file included instead.
Look for things with context. I hope nobody does this, but someone could open a namespace and include a header file. So if you change include order things compile differently. Find and remove all rubbish like that.
Now make all headerfiles standalone. That means a C++ source file stating just “#include myheader.h” must compile. So you comment out all include statements. Then try compiling the first header file. If it doesn’t compile fix it by making it include everything it needs. If a.h needs something from b.h then you include b.h. If b.h doesn’t compile on its own then you fix it first and so on until all your header files compile and act the same no matter how they are included.
Then you do the same with your source files. And then your main can build with the source files you want after adding everything needed to fix linker errors.
Now if you find you have a huge source file that includes some small utility that you need, and a huge bunch of stuff you don’t care about, you split it up. And so on.
objdump
orreadelf
to extract the linker tables from the object code to see which other functions it depends on. This is 100% reliable, but tedious and only gives us objects with linkage (e.g. functions, extern variables). It cannot tell us anything about classes, templates, typedefs, macros, and so on. If OP is just trying to navigate the source code, a language server likeclangd
might be more appropriate (or a conventional C++ IDE).gcc --coverage
) and use a tool to draw the call graph. Unlike linker stuff this won't be perfect, but it might highlight the most important relationships.