C语言 为什么这个Makefile是错误的?链接器只有在编译器错误之前才会失败

bwntbbo3  于 2023-02-18  发布在  其他
关注(0)|答案(1)|浏览(119)

这是一个示例程序,使它更容易解释。有这4个文件,main.c,sum.c和header.h。最后是Makefile。
main.c

#include <stdio.h>
#include "header.h"

int main()
{
    int a = 1;
    int b = 1;
    int c = sum(a, b);
    
    printf("Sum: %i\n",c);

    return (0);
}

sum.c

#include "header.h"

int sum(int a, int b)
{
    return (a + b);
}

header.h

int sum(int a, int b);

生成文件

TEST_SRCS = *.c 
TEST_OBJS = $(TEST_SRCS:%.c=%.o)

%.o : %.c *.h
    gcc -c $^

assemble_test: $(TEST_OBJS);
    
test: assemble_test 
    gcc -o test *.o
    ./test

clean:
    @rm -rf *.o *.gch test
    @echo "Cleaned"

重现步骤:

  • 呼叫测试规则:使测试〉全部正常。
  • 故意引入任何错误,例如两个逗号:
printf("Sum: %i\n",,c);
  • 呼叫测试规则:make test〉获取常规语法错误。
  • 删 debugging 误。保存文件。
  • 呼叫测试规则:make test〉无论如何都会得到链接器错误。
gcc -o test *.o
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [test] Error 1
  • 每次使用清理规则重新启动。

有这样的行为一段时间了,我想不出问题所在。老实说,我是makefiles的新手,所以我一定是做错了什么。
关于调用assemble_test的测试规则。这是因为一个更大的Makefile的一部分,我需要不同的规则用于不同的目的来编译对象,所以不要介意。
你能帮我搞清楚到底是怎么回事吗?
谢谢。

but5z9lq

but5z9lq1#

在目标文件中使用通配符是错误的,通配符匹配的是make运行时磁盘上 * 已经存在 * 的文件,这没有帮助,因为它们显然不会匹配 * 还不存在 * 的文件,而makefile的全部意义就是创建不存在的文件。
所以这个:

TEST_SRCS = *.c 
TEST_OBJS = $(TEST_SRCS:%.c=%.o)

TEST_SRCS的值保留为字符串*.c,将TEST_OBJS的值保留为字符串*.o(也许您认为通配符会立即扩展,但不,事实并非如此)。
然后这一行:

assemble_test: $(TEST_OBJS);

使目标assemble_test*.o列为先决条件:这将扩展到目录 * 中已经存在的所有目标文件。当然,它不会扩展到您希望make创建但还不存在的目标文件。
这里还有很多其他的问题:例如,你不想编译$^,因为它扩展到了 * 所有 * 先决条件,但你只想编译源文件,而不是头文件。
假设您使用的是GNU make,您可能需要这样的代码:

TEST_SRCS := $(wildcard *.c )
TEST_OBJS = $(TEST_SRCS:%.c=%.o)

%.o : %.c *.h
        gcc -c $<

test: $(TEST_OBJS)
        gcc -o $@ $^
        ./$@

通过使用wildcard函数,您可以在将结果替换为.o之前扩展sources glob first 的值。

相关问题