c语言 - 生成文件先决条件是否应列出共享对象



我知道,对于许多使用公共共享库的进程,共享库中的二进制代码可以更新,而不必更新所有这些进程。只要是内部实现更改,并且不删除导出的函数或更改导出函数的参数就可以了。

我不确定如何将其与 Makefile 依赖项协调。简单的准则是,如果文件被任何命令引用,则它是一个依赖项,应作为先决条件在 Makefile 规则中列出。

链接可执行文件时,它肯定可以引用共享对象,因此依赖于该共享对象。但是,似乎并不总是因为共享对象发生了变化而需要重新链接。

所以我想知道将库列为依赖项:

all: process
# listing library.so as dependency
process: file.o library.so
gcc -o process file.o library.so
library.so: library.o
gcc -shared -o library.so library.o
library.o: library.h

与不列出它:

all: library.so process
# not listing library.so as dependency
process: file.o
gcc -o process file.o library.so
library.so: library.o
gcc -shared -o library.so library.o
file.o: library.h
library.o: library.h

假设library.h包含从library.so导出的所有函数的声明。

如果library.soprocess的依赖关系,那么似乎如果我只更改函数的实现(不更改导出的函数签名),那么我不需要重新链接process,但是make命令会重新链接library.so,然后反过来重新链接process

但是,如果library.so不是process的依赖项,那么make仍然会通过all目标重新链接library.so以实现更改,但不会重新链接process。如果我更改函数参数的数据类型、添加/删除函数参数或添加/删除函数,则library.h将进行更改。这将反过来触发重新编译file.o,进而触发重新链接process

使用library.h来控制file.o的重新编译,因此间接控制process的重新链接仍然是不精确的,因为file.o实际上可能没有引用任何从更改 library.so 导出的函数。

我回顾了这个问题,但我找不到有关进程共享对象依赖项的任何具体信息: 生成文件依赖项,什么是依赖项?

如果您不将library.so列为process的依赖项,如果您修改其源之一(library.so的源文件),则很可能以与程序process不兼容library.so结束,并且当您尝试执行它时,您的程序可能会崩溃。

认为您更改了库,消除了从中f()的功能,因为您不再需要它......但是您的程序仍然process在其main()函数中调用它。 由于您没有修改process.o(您没有接触它的任何源代码),因此不会对其进行编译,也不会执行新的链接命令(因为process仅取决于process.o)。

上次链接process链接器在 main 中调用了f(),并决定将其放在地址x(对应于library.so中存在的地址)。 但是,由于您没有说明如果library.so发生变化,process需要链接,因此不会链接...当你执行它时,它会在地址x调用f()并崩溃。

试试这个,你会发现如果你把依赖留在library.so,那么你的程序将被链接到共享库,并会抱怨f()不存在。 所以你应该修改process.c并重复。

总是这样想...链接process是否需要文件library.so如果是,那么您应该依赖它。 确实如此,因为您在library.so中编写的函数是从process调用的。 您将看到.h文件的依赖项放在.o目标上,而不是放在.c文件上。 这是因为需要.c和所有包含的.h文件来生成.o对象。 但是.c文件不依赖于.h文件...取决于编译的结果(这是.o文件)。

第二个文件,对目标all有假依赖。 这就是所谓的.PHONY:目标(始终执行的目标,不需要创建文件)使用它,您可以尝试创建library.soprocess。 如果在链接进程时存在library.so,那么它将被包含(但不知道它是最近的 buid 还是旧的),但如果不是,当你尝试构建进程时,如果library.so尚不存在,那么你会收到链接器的强烈抱怨,你的构建将被中止。

因此,作为结论,第二Makefile是不正确的,您应该避免它。 在检查依赖项时make(1)声明依赖项。

最后要注意的是,根据 Make 的实现,规则右侧的依赖项顺序可能很重要,也可能不重要。 如果您在多处理器上运行 make 并尝试执行并行构建,library.so放在process的左侧可能是一个坏主意(请参阅make(1)的选项-j)。 在并行构建中,make(1)在满足依赖文件的所有依赖项之前不会开始构建依赖文件......但它尝试启动尽可能多的进程,以在多处理器计算机上处理这种可能性。 如果您拥有完整的内核集,构建过程会加快很多速度,但如果您不精确观察依赖项,则可能会很危险。

相关内容

  • 没有找到相关文章

最新更新