gpt4 book ai didi

c - Makefile: "ld: can' t 与主可执行文件链接”在 C

转载 作者:太空宇宙 更新时间:2023-11-03 23:45:01 25 4
gpt4 key购买 nike

我正在尝试将两个 c 文件 calutil.ccalutil.h 编译成一个可执行文件。这是我的生成文件:

CC = gcc
CFLAGS = -Wall -std=c11 -DNDEBUG

all: caltool

caltool: calutil.o caltool.o
$(CC) $(CFLAGS) calutil.o caltool.o

caltool.o: caltool.c
$(CC) $(CFLAGS) caltool.c -o caltool.o

calutil.o: calutil.c
$(CC) $(CFLAGS) -c calutil.c -o calutil.o
clean:
rm -rf *.o *.out
calutil.c 没有 main ,而 caltool.cmain. 我收到错误
ld: can't link with a main executable file 当我 make 。这是什么原因?

最佳答案

主要问题是您的某些链接方法缺少输出文件,并且您的编译缺少 -c

如果您使用 GNU make,以下 Makefile 就足以完成您想做的事情:

CFLAGS:=-Wall -std=c11
CPPFLAGS:=-DNDEBUG

.PHONY: all
all: caltool

caltool: caltool.o calutil.o

.PHONY: clean
clean::
$(RM) *.o

解释:
  • 当您不使用特定于目标的变量时,您应该使用 := 而不是 = 来分配变量,以便它们在分配时而不是在评估时扩展。
  • 当您的 Makefile 增长并拆分它时,您可能希望有多个名为 clean 的目标,它们都将被执行。在这种情况下,使用 clean:: 而不是 clean:
  • 有一个预定义的变量来调用 rm ,它是 $(RM) 并且它包含 -f 标志以防止 Makefile 失败,以防一个或多个要删除的文件首先不存在。
  • clean 的模式应该是 *.[adios](这真的很容易记住,adios 是西类牙语的再见),以便它删除中间文件(构建自己的静态库时为 .a)、依赖文件( .d )、预处理器输出( .i )和汇编程序文件 ( .s ),以防您使用 -save-temps 来查看编译器在做什么。
  • GNU make 有内置的编译和链接规则,参见 http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=3.81
  • 内置的编译规则调用 $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<,因此您无需编写自己的规则。
  • 链接调用的内置规则 $(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@
  • 不是文件本身的目标应该声明为 .PHONY 以防止在用户创建具有相同名称的文件时混淆,例如 allclean
  • 我看不到您的任何命令如何创建与 glob 模式 *.out 匹配的文件,因此我删除了 clean 规则的那部分。
  • 预处理器的标志应该进入 CPPFLAGS 而不是 CFLAGS 。预处理器标志通常都是 -D-I 标志,并且还会传递给在同一项目中使用 C 预处理器的其他工具,如 splintPC-Lint

  • Makefile 运行时,它正在寻找如何制作 all ,它发现对于 all 它必须制作 caltool 。对于 caltool 它发现它必须首先制作 calutil.ocaltool.o 。当它尝试生成 calutil.ocaltool.o 时,它​​发现它可以从 calutil.ccaltool.c 生成它们并且会这样做。然后它将 caltool.ocalutil.o 链接到 caltool

    从你的命名我猜到它是包含 caltool.c 函数的 main() 。使用静态链接库后,首先放置包含 main() 的对象会很有帮助。

    编辑:这里有一些更多的魔法给你。我假设您有一个头文件 calutil.h ,它包含在 caltool.c 中以访问 calutil.c 提供的外部符号。您希望重建依赖于这些头文件的所有对象。在这种情况下,将以下行添加到您的 Makefile 中:
    CPPFLAGS+=-MMD
    -include caltool.d calutil.d

    为了不多次获得对象列表,您可以添加一个变量 objects ,如下所示:
    objects:=caltool.o calutil.o

    然后,您将使用以下规则构建应用程序:
    caltool: $(objects)

    并包含这样的依赖文件:
    -include $(objects:.o=.d)

    如果您保持工作树“干净”,即不要用“外来”代码“污染”它,即您总是希望在项目中包含所有 .c 文件,您可以按如下方式更改 objects 的定义:
    sources:=$(wildcard *.c)
    objects:=$(sources:.c=.o)

    如果您想知道为什么它是 CPPFLAGS(大写)而不是 objects(小写):通常对所有配置规则配方和控制 make 的内置行为的变量使用大写,在它之上构建的工具,以及经典的环境变量,其他所有的小写变量。

    关于c - Makefile: "ld: can' t 与主可执行文件链接”在 C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35399830/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com