I am currently working on a flexible C/C++ build framework that I’ll (hopefully) open source fairly soon. (see this question for some background).
I am using the below command to generate the #include file dependencies for source/header files.
gcc -M -MM -MF
Is there a way of cleverly inferring linker (.o file) dependencies for executables (unit tests + main executable for target platform in my case) using gcc/GNU utilties in a similar way to above? Currently the framework makes a whole lot of assumptions and is pretty dumb in determining these dependencies.
I have heard of one approach where the nm command can be used to come up with a list of undefined symbols in an object file. For example, running nm on an object file (compiled using gcc -c) comes up with something like this –
nm -o module.o
module.o: U _undefinedSymbol1
module.o: U _undefinedSymbol2
module.o:0000386f T _definedSymbol
One would then look for other object files where these undefined symbols are defined to come up with a list of object file dependencies required to successfully link the file.
Is this considered best practice in determining linker dependencies for executables? Are there any other ways of inferring these dependencies? Assume that all object files already exist (i.e. have already been compiled using gcc -c) when proposing your solution.
If there are multiple executables (or even a single executable) that need different sets of dependencies, then the normal, classic way to handle that is to use a library — static
.aor shared.so(or equivalent) — to hold the object files that can be used by more than one program, and to link the programs with that library. The linker automatically pulls the correct object files out of a static archive. The shared library process is a little different, but the net result is the same: the executable has the correct object files available to it at runtime.For any program, there is at least one file unique to the program (normally, that’s the file that contains the
main()program). There may be a few files for that program. Those files are probably known about and can be listed easily. The ones that you might need depending on configuration and compilation options are probably shared between programs and are easily handled via the library mechanism.You have to decide whether you want to use static or shared libraries. Creating shared libraries well is harder than creating static libraries. On the other hand, you can update a shared library and immediately affect all the programs that use it, whereas a static library can be changed but only programs that are relinked with the new library benefit from the changes.