我有两个.c文件,我在makefile上编译。
foo.c的:
void foo()
{
printf("this is foo");
}
main.c中:
#include <stdio.h>
int main()
{
printf("this is main\n");
foo();
}
makefile看起来像这样:
all: main.o foo.o
gcc -o prog foo.o main.o
main.o: main.c
gcc -c main.c
foo.o: foo.c
gcc -c foo.c
所以问题是: 如何在没有我的情况下使用printf()包括stdio.h以及main.c如何在没有我的情况下使用方法foo()包括foo.c。
我的猜测/研究是makefile作为链接器工作。但我没有证明这一点,并希望了解这是如何工作的。
如果我误解了某些事情,请纠正我。
答案 0 :(得分:0)
makefile不是链接器。它是输入。 makefile只是告诉make在什么条件下执行什么命令。
您的all
目标在链接/链接器模式gcc
中正在运行gcc -o prog foo.o main.o
。
与foo.o
和main.o
目标在编译模式gcc
中运行gcc -c foo.c
的方式相同。
对于记录,您可以将两个.o
目标合并到
%.o: %.c
gcc -c $^
实际上,它已经是make中的默认规则,因此您根本不需要包含该规则。
此外,您的all
目标不遵循投注习惯,因为它会生成与目标名称不匹配的文件。所以你应该使用
all: prog
prog: main.o foo.o
gcc -o prog foo.o main.o
代替。
虽然默认情况下会再次出现,因此您的整个makefile可以替换为
all: prog
prog: main.o foo.o
你应该得到相同的结果。
答案 1 :(得分:0)
在makefile中,您可以强制编译器包含<stdio>
或任何其他标题:
来自文档:
-include file
处理文件,好像#include&#34; file&#34;出现了作为第一行 主要源文件。但是,搜索文件的第一个目录是 预处理器的工作目录而不是目录 包含主要源文件。如果在那里找不到,则搜索它 因为#include&#34; ...&#34;的其余部分搜索链正常。如果 给出了多个包含选项,文件包含在 命令它们出现在命令行中。
只需在makefile中的GCC /编译器命令行中添加-include filename.h
。
答案 2 :(得分:0)
在编译阶段,编译器会根据原型检查函数调用。任何缺少原型的函数都假定返回int
并接受任意数量的参数。
如果您调高警告级别,gcc会在原型丢失时发出警告。您应该添加-Wall
,还可以添加-pedantic
以获取编译器认为可疑的其他内容的诊断信息。
如果编译步骤成功,编译器将创建一个包含已编译代码和2个引用表的目标文件。第一个表是导出表。它包含从目标文件导出的所有函数和变量的名称。 第二个表是导入表。它包含所引用的所有函数和变量的列表,但缺少声明的位置。
在你的情况下,我们有:
<强> foo.o的:强>
导出:
foo
导入:
printf
<强> main.o 强>
导出:
main
导入:
printf
foo
在链接器阶段,链接器将获取导入和导出列表并匹配它们。除了在命令行中指定的目标文件和库之外,链接器还将自动与libc链接,libc包含c语言定义的所有函数。