【问题标题】:Final step in GCC compiling (ld) issueGCC 编译 (ld) 问题的最后一步
【发布时间】:2018-05-05 14:08:01
【问题描述】:

我正在尝试编写一个逐步编译的makefile,问题出在第四步,链接。

程序由多个文件组成,以main.c开头:

#include "file1.h"
#include "file2.h"

int main() {
  printout1("Print one");
  printout2(5);
  return 0;
}

file1.h

#include <stdio.h>

void printout1(char *str);

file1.c

#include "file1.h"

void printout1(char *str) {
  printf("%s\n", str);
}

file2.h

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

void printout2(int);

file2.c

#include "file2.h"

void printout2(int val) {
  printf("%d\n", val);
  printout1("Print two");
}

我正在尝试使用以下 makefile 编译此程序:

all:
    cpp main.c main.i 
    gcc -S main.i
    as -o main.o main.s
    ld -o main.o

出现以下错误:

ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0
main.o: in function 'main':
main.c:(.text+0xa): undefined reference to 'printout1'
main.c:(.text+0x14): undefined reference to 'printout2'
makefile:2 recipe for target 'all' failed
make:***[all] Error 1

我对这类事情还很陌生,我知道问题出在头文件上,我只是不知道如何将它们包含在其中。

【问题讨论】:

  • 你在哪里编译 file2.cfile1.c(或者链接它们)?
  • main.o 调用 printout1,但未与提供它的目标文件链接
  • 你为什么要组装?通常的方法是直接为all源文件生成object文件,然后链接allobject文件。
  • 此外,当您使用 GCC 构建时,您需要更多的目标文件和库,gcc 前端程序提供给 ld,但您不需要。
  • 最后,如果你想像这样通过汇编,直接使用链接器,那么使用--verbose 选项到gcc 来查看它使用了哪些命令、标志和库

标签: c gcc ld


【解决方案1】:

两个主要问题:

  1. gcc 是所有必需步骤的前端——不要尝试直接调用工具链中的其他工具,始终使用gcc。这将确保它始终为这些其他工具添加所需的选项。

  2. 您在不同的编译单元(file1 和 file2)中有函数,但从不编译和链接这些。


具有您的结构的 GNU make 的合理 Makefile 如下所示:

CC ?= gcc

all: main

main: main.o file1.o file2.o
    $(CC) -o$@ $^

%.o: %.c
    $(CC) -c -o$@ $<

.PHONY: all

这会将所有.c 文件直接编译为目标文件,最后将它们(使用$(CC),例如gcc)链接到您的最终可执行文件。规则all 被标记为.PHONY,因为它不会创建一个名为all 的文件——您应该让make 知道这一点。

您当然可以显式添加额外的步骤,但这没有多大意义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 2020-09-22
    • 2010-10-21
    相关资源
    最近更新 更多