我如何才能弄清楚正确的依赖项以链接到正确的下游目标文件中? [英] How do I get make to figure out the correct dependencies to link in the correct downstream object files?

查看:166
本文介绍了我如何才能弄清楚正确的依赖项以链接到正确的下游目标文件中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将用一个小例子作为参考。考虑一个项目:

  inner_definitions.o:inner_definitions.cpp inner_definitions.h 
gcc $ ^ -o $ @

inner_class_1.o:inner_class_1.cpp inner_class_1.h inner_definitions.h
gcc $ ^ -o $ @

inner_class_2.o:inner_class_2.cpp inner_class_2.h inner_definitions.h
gcc $ ^ -o $ @

outer_class.o:outer_class.cpp outer_class.h inner_class_1.h inner_class_2.h
gcc $ ^ -o $ @

executable.o:executable.cpp executable.h outer_class.h
gcc $ ^ -o $ @

可执行文件:__?1__
__? 2__

但填入空格 __?1 __ 链接器依赖关系,而 __?2 __ 并不容易。在这个小例子中,人们可以争辩说很容易看到 __?1__ = inner_definitions.o inner_class_1.o inner_class_2.o outer_class.o executable.o 。然而,这显然不是一个可扩展的解决方案,因为它会迫使每个开发人员理解他们正在使用的代码的所有依赖关系,以便他们可以手动计算依赖关系而不是使用<$ c

另一个解决方案是为每个对象文件都有一个不同的变量,它列出了它的所有下游依赖关系:即 make code> __?1__ = executable.o $(executable_dependencies)。这不是一个理想的解决方案,因为它强制makefile以特定方式编译,所以变量只能在完全定义时才使用。另外,对于真正的大型应用程序,这些变量可能会超过最大变量长度。



另一个解决方案是使用归档.a文件进行链接。在这种情况下,我们可以构造一个 inner_class_1.a ,它包含 inner_defintions.o inner_class_1.o ,因此它可以与任何需要 inner_class_1.o 的对象文件链接,而不会强迫开发人员重新构建依赖关系。这种方法看起来很有前途,但涉及到许多重复文件。此外,它看起来并不像 gcc 链接器可以处理嵌套的归档文件。



是否有另一种方法?什么是最好的方法? gcc 链接器可以处理嵌套的存档文件吗?

解决方案

正在尝试自动化(选择正确的目标文件以满足所有引用)通常留给链接器,使用静态库(.a文件)将候选目标文件分组,如同您所建议的那样。



您可能会遗漏一个重要细节:如果您将链接器传递给一个存档,它将仅链接到实际需要的存档文件中。因此,您可以在相当粗略的粒度级别下创建归档,而不必让所有可执行文件变得庞大 - 链接器将选择它所需的内容 - 尽管如果您采用这种方法太过简单,最终可能会以不必要的缓慢构建结束。



GNU链接器不会将对象从嵌套库中取出。如果你想通过合并许多小型图书馆来建立一个大型图书馆,你可以通过 ar脚本。这将为您提供一个包含所有对象文件的存档,而不包含任何嵌套的库结构。



如果重复的.o文件和包含相同对象的.a文件躺在身边的代码困扰你,精美的手册描述了一种方法来使直接更新档案


I'm going to use a small example for reference. Consider a project with:

inner_definitions.o : inner_definitions.cpp inner_definitions.h
    gcc $^ -o $@

inner_class_1.o : inner_class_1.cpp inner_class_1.h inner_definitions.h
    gcc $^ -o $@    

inner_class_2.o : inner_class_2.cpp inner_class_2.h inner_definitions.h
    gcc $^ -o $@

outer_class.o : outer_class.cpp outer_class.h inner_class_1.h inner_class_2.h
    gcc $^ -o $@

executable.o : executable.cpp executable.h outer_class.h
    gcc $^ -o $@

executable : __?1__
    __?2__

But filling in the blanks __?1__ for the linker dependencies and __?2__ for the linker command isn't easy.

In this small example, one could argue that its easy to see that __?1__ = inner_definitions.o inner_class_1.o inner_class_2.o outer_class.o executable.o . However, this is clearly not a scalable solution as it forces each developer to understand all the dependencies of the code they are working with so they can figure out the dependencies by hand rather than by using the make utility.

Another solution would be to have a different variable for each object file that listed all its downstream dependencies: i.e __?1__ = executable.o $(executable_dependencies). This is not a desired solution because it forces the makefile to be compiled in the specific way so the variables are only used when they are fully defined. Also, for really large applications these variables might exceed the maximum variable length.

Yet another solution is to use archive .a files for linking. In this case, we could construct an inner_class_1.a that included both inner_defintions.o and inner_class_1.o, so it could be linked with any object file that needed inner_class_1.o without forcing the developer to reconstruct the dependencies. This approach seems promising, but involves having many duplicate files. Also, it doesn't appear that the gcc linker can handle nested archive files.

Is there another approach? What is the best approach? Can the gcc linker handle nested archive files?

解决方案

The job you're trying to automate (picking the right object files to satisfy all references) is usually left to the linker, using static libraries (".a" files) to group the candidate object files, just as you suggest.

An important detail you may be missing: If you pass the linker an archive, it will only link in those files from the archive that are actually needed. So you can create archives at a fairly coarse level of granularity without necessarily bloating all your executables -- the linker will pick just what it needs -- although can easily end up with needlessly slow builds if you take this approach too far.

The GNU linker will not pull objects out of nested libraries. If you want to make one big library by merging many small ones, you can do that with the "addlib" command in an ar script. That will give you a single archive containing all of the object files without any nested library structure.

If the duplication of having .o files and .a files containing the same object code lying around bothers you, the fine manual describes a way to have make update the archives "directly".

这篇关于我如何才能弄清楚正确的依赖项以链接到正确的下游目标文件中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆