为 C/C++ 可执行文件自动生成目标文件(链接器)依赖项
我目前正在开发一个灵活的 C/C++ 构建框架,我将(希望)很快将其开源.(有关背景信息,请参阅这个问题).
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).
我正在使用以下命令为源/头文件生成#include 文件依赖项.
I am using the below command to generate the #include file dependencies for source/header files.
gcc -M -MM -MF
有没有一种方法可以巧妙地推断 可执行文件 的链接器(.o 文件)依赖项(在我的情况下,单元测试 + 目标平台的主要可执行文件)使用 gcc/GNU 实用程序以与上述类似的方式?目前,该框架做出了很多假设,并且在确定这些依赖关系方面非常愚蠢.
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.
我听说过一种方法,可以使用 nm 命令在目标文件中列出未定义符号的列表.例如,在目标文件(使用 gcc -c 编译)上运行 nm 会产生类似这样的结果 -
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.
这是否被认为是确定可执行文件的链接器依赖关系的最佳实践?有没有其他方法可以推断这些依赖关系?在提出您的解决方案时,假设所有目标文件都已经存在(即已经使用 gcc -c 编译过).
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.
推荐答案
如果有多个可执行文件(甚至是单个可执行文件)需要不同的依赖集,那么正常的、经典的处理方法是使用库― 静态 .a
或共享 .so
(或等效项) ― 保存可由多个程序使用的目标文件,并将程序与该库链接.链接器会自动从静态存档中提取正确的目标文件.共享库过程略有不同,但最终结果是相同的:可执行文件在运行时具有可用的正确目标文件.
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 .a
or 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.
对于任何程序,至少有一个程序唯一的文件(通常是包含 main()
程序的文件).该程序可能有几个文件.这些文件可能是已知的并且可以很容易地列出.根据配置和编译选项,您可能需要的那些可能在程序之间共享,并且可以通过库机制轻松处理.
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.
相关文章