I wrote a program that scanned object files (compiled from a large C++ project) to see how they were interdependent. It was pretty useful for detecting cycles in the shared libraries that we were compiling from them, but the biggest benefit was it enabled me to very easily rewrite the build system from scratch.
It was surprisingly simple - most ELF parsers can read a file and dump the symbol tables in them. (In this context, a symbol means a defined function, so if a C/C++ source file has intmain() in it, the corresponding .o file will have a main symbol in it.) They also include information about which symbols are defined in the .o file, as well as which symbols it depends on which are undefined. This allows you to figure out a dependency graph, which you can easily visualize using graphviz or use to autogenerate build files for CMake or any other build system you may wish to use.
In my case, I wrote this kind of program twice in two separate jobs. Both of them had a very janky build system using custom Makefiles. I used this program to rewrite the build systems in CMake. The graphviz dependency graphs are also just generally helpful to have as project documentation. CMake can do this natively, by the way - here’s the documentation for it: https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-cmake-graphviz
I wrote a program that scanned object files (compiled from a large C++ project) to see how they were interdependent. It was pretty useful for detecting cycles in the shared libraries that we were compiling from them, but the biggest benefit was it enabled me to very easily rewrite the build system from scratch.
It was surprisingly simple - most ELF parsers can read a file and dump the symbol tables in them. (In this context, a symbol means a defined function, so if a C/C++ source file has
int main()in it, the corresponding.ofile will have amainsymbol in it.) They also include information about which symbols are defined in the.ofile, as well as which symbols it depends on which are undefined. This allows you to figure out a dependency graph, which you can easily visualize using graphviz or use to autogenerate build files for CMake or any other build system you may wish to use.In my case, I wrote this kind of program twice in two separate jobs. Both of them had a very janky build system using custom Makefiles. I used this program to rewrite the build systems in CMake. The graphviz dependency graphs are also just generally helpful to have as project documentation. CMake can do this natively, by the way - here’s the documentation for it: https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-cmake-graphviz