假设我有一个简单的c库项目,布局如下
- src/
- square_root.c
- log.c
- power.c
- newton_method.c
- include/
- square_root.h
- log.h
- power.h
- newton_method.h
现在,我想创建一个简单的程序(main.c)来调用 square_root()
# main.c
# include "square_root.h"
int main()
{
printf("%f\n", square_root(4.0));
return 0;
}
要编译 main.c,必须将 newton_method.c 包含到构建中。
gcc main.c src/square_root.c src/newton_method.c -o main
在本例中,newton_method.c 是 square_root.c 的依赖项。 如果库很大或编写得不好,那么查找源代码的依赖关系就会变得很困难。 当然,可以在构建过程中包含所有 *.c,但这会使构建过程缓慢且笨拙。
我试过了
gcc -H -MM -M main.c
但它只给了我 *.h 而不是 *.c
是否有任何工具可以查找源代码的依赖关系?
最佳答案
解决方案
执行此操作的标准方法是此 paper 中描述的方法。由 Paul Smith(GNU Make 的当前维护者)编写。此方法使用 GCC 选项 -MMD -MP -MF -MT
来检测每个目标文件 *.o
的依赖关系。然后,它创建依赖项文件 *.d
并用构建每个对象的规则填充它们,包括所有必要的依赖项(源和 header )。引用这个page如果您想了解有关 GCC 选项的更多信息。对于您的情况,以下 makefile 应该足够了:
SRCS := main.c square_root.c newton_method.c
BIN := main
SRCS := $(SRCS:%=src/%)
OBJS := $(SRCS:src/%.c=obj/%.o)
DEPS := $(OBJS:%.o=%.d)
all: $(BIN)
$(BIN): $(OBJS)
gcc -o $@ $^
obj/%.o: src/%.c obj/%.d
gcc -c -I include -MMD -MP -MF $(patsubst obj/%.o,obj/%.d,$@) -MT $@ -o $@ $<
$(DEPS):
-include $(DEPS)
关于 makefile 的观察:
- 您必须将 makefile 放在根目录中。
- 当您将代码复制到 makefile 时,请注意缩进部分(每条规则的说明)。每个命令行必须以
TAB
字符开头,而不是空格。 - 我假设所有源文件
*.c
都在目录src/
中,并且所有头文件*.h
位于目录include/
中。 - 编译器会将所有目标文件
*.o
和依赖文件*.d
放在目录obj/
中。我假设该目录已经存在。 - 您可以通过修改变量
SRCS
来选择涉及的源文件,但只有其中一个可以包含main()
函数。 - 您可以通过修改变量
BIN
来选择可执行文件的名称。 - 可执行文件将在根目录中创建。
测试设置
我尝试根据您所说的内容重现您的场景。为了测试 makefile,我使用了以下源文件和头文件。
src/main.c
#include <stdio.h>
#include "square_root.h"
int main()
{
printf("%f\n", square_root(4.0));
return 0;
}
include/square_root.h
float square_root(float x);
src/square_root.c
#include "square_root.h"
#include "newton_method.h"
float square_root(float x)
{
return newton_method(x);
}
include/newton_method.h
float newton_method(float x);
src/newton_method.c
#include "newton_method.h"
float newton_method(float x)
{
return x;
}
依赖文件
下面是编译器创建的依赖文件。您将看到每个文件都有一个规则来构建目标文件,并以所有依赖项(源和 header )作为先决条件。编译器还为除主源文件之外的每个依赖项添加一个目标,导致每个依赖项不依赖任何内容。如果您删除头文件而不更新 makefile 来匹配,这些虚拟规则可以解决 GNU Make 给出的错误。所有这一切都是自动完成的。很酷吧? :)
main.d
obj/main.o: src/main.c include/square_root.h
include/square_root.h:
square_root.d
obj/square_root.o: src/square_root.c include/square_root.h \
include/newton_method.h
include/square_root.h:
include/newton_method.h:
newton_method.d
obj/newton_method.o: src/newton_method.c include/newton_method.h
include/newton_method.h:
关于c - 如何找到源代码的依赖关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68766826/