【问题标题】:Creating a makefile - (C)创建生成文件 - (C)
【发布时间】:2018-03-20 10:49:18
【问题描述】:

我正在尝试创建一个简单的 makefile。我有一个头文件:“guiBuilder.h”。我有另一个文件将使用它:“client.c”。我使用的makefile是:

HEADERS = guiBuilder.h

default: program

program.o: client.c $(HEADERS)
    gcc -c client.c -o client.o

program: client.o
    gcc client.o -o Client

我在这里找到了makefile的代码:

How do I make a simple makefile for gcc on Linux?

我现在在运行时收到此错误:

(.text+0x20): 对 `main' 的未定义引用 collect2:错误:ld 返回 1 个退出状态 Makefile:9:目标“程序”的配方失败 make: *** [程序] 错误 1

【问题讨论】:

  • 如果你不使用 Makefile 会构建吗?
  • program.o 的规则生成client.o
  • 另外,client.c 中是否有“主”子程序?不使用 make 能否成功构建,如果可以,如何构建?
  • 你有多少个源文件?程序.c 和客户端.c ?主程序在哪里?有没有?
  • @PierredeBuyl program 的规则创建Client。是的,这不是 make 的工作原理...

标签: c makefile


【解决方案1】:

make 文件中的规则格式如下:

target: dependency1 dependency2 etc
    command to build target

target您要构建的文件的名称。所以这条线

program: client.o
    gcc client.o -o Client

正在尝试构建一个名为 program 的文件。但是,该命令不会创建名为 program 的文件,而是创建名为 Client 的文件。这比您想象的问题要小,它只是意味着无论Client 是否是最新的,都会始终执行该规则。但是,您应该更改它,以便目标是您正在构建的文件。

Client: client.o
    gcc client.o -o Client

顺便说一下,在大多数 *nixes 中,文件名区分大小写,例如 Clientclient 在 Linux 上是不同的文件。

该规则有一个依赖项:client.o。不幸的是,您的 make 文件不知道如何构建 client.o - 没有名为 client.o 的目标。

我推测你的错误的原因是你有一个旧的client.o 挂在它上面没有main() 函数。这就是链接(program 目标中的gcc 命令)失败的原因。

目标program.o与目标program有同样的问题。您不是在构建 program.o,而是在构建 client.o。此目标需要更改为

client.o: client.c $(HEADERS)
    gcc -c client.c -o client.o

这很高兴是您的 Client 目标的依赖项。

注意 make 规则的命令部分的缩进必须使用制表符完成。如果复制粘贴我的答案或任何其他答案,或者链接问题中的答案,请确保您的缩进是制表符,而不是空格。

更新test() 是未定义引用的问题)

如果您在guiBuilder.c 中有一个在guiBuilder.h 中有原型的函数,您需要编译guiBuilder.c 并将其添加到链接阶段。

guiBuilder.o 的规则看起来与 client.o 的规则非常相似

guiBuilder.o: guiBuilder.c $(HEADERS)
    gcc -c guiBuilder.c -o guiBuilder.o

那么你需要添加guiBuilder.o作为Client的依赖

Client: client.o guiBuilder.o
    gcc client.o guiBuilder.o -o Client

您可能已经注意到,您现在有两个用于创建.o 文件的规则,除了源文件和目标文件的名称之外,它们都相同。 the question that you linked 接受的答案显示了如何修改 make 文件,因此您只需要定义一次规则。

【讨论】:

  • 好的,现在我得到 client.c:(.text+0x2d): undefined reference to `test' 当我运行 makefile 时。我在 client.c 中包含了 guiBuilder.h
  • @ChristopherLittlewood test 声明在哪里?
  • 是的。 test 在 guiBuilder.c 中声明并在 guiBuilder.h 中引用
  • 然后我在client.c中调用它
  • 我想通了。我需要在 client.c 中将引用从 guiBuilder.h 更改为 guiBuilder.c
【解决方案2】:

我建议您阅读GNU Make manual 以更好地了解make 命令和makefile 的工作原理。

为了回答你的问题,简而言之,Makefile 由几个东西组成,其中基本的东西是targetdependencyrecipe。如下方式

target: dependency  
        recipe

当您运行 make 命令时,它会搜索名称为 Makefilemakefile 的文件,并开始解析目标和依赖项并执行该目标的配方。

在您的 makefile 中,您想创建名称为 program 的最终二进制文件,但您没有 program.c,因此您的 makefile 应该如下所示:

HEADERS = guiBuilder.h

all: program

client.o: client.c $(HEADERS)
          gcc -c client.c

program: client.o
         gcc client.o -o program

【讨论】:

  • 为什么要重新排序规则?它们的顺序根本不重要,除了出现的第一条规则自动是 default 规则。
  • 将规则编辑为具有序列顺序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-06
  • 2015-09-21
  • 1970-01-01
  • 2018-07-02
  • 2016-10-05
  • 1970-01-01
相关资源
最近更新 更多