【问题标题】:Linking files on a raspberry pi and getting issues在树莓派上链接文件并遇到问题
【发布时间】:2020-11-24 14:39:43
【问题描述】:

我有 5 个文件,我试图在树莓派上使用 gcc 链接,我浏览了一些帖子,但我似乎找不到解决这个问题的方法,所以我想问问是否有人可以看看我做错了什么。

我运行的 make 文件看起来像这样

Mainfile: 
    gcc -c ./Include/func_1.c 
    gcc -c ./Include/func_2.c
    gcc -c ./Include/func_3.c
    gcc -c ./Include/func_4.c 
    gcc -c ./Include/func_5.c 
    gcc -c Mainfile.c 

    gcc -o Mainfile func_1.o func_2.o func_3.o func_4.o func_5.o Mainfile.o
    

第 1 - 6 行似乎工作正常,我设法制作了目标文件,但是当我尝试将它们链接到第 8 行中的 Mainfile 时,出现以下错误

/usr/bin/ld: /tmp/cc5NQuqi.o: in function `main':
Mainfile.c:(.text+0xfc): undefined reference to `func1_1'
/usr/bin/ld: Mainfile.c:(.text+0x104): undefined reference to `func1_2'
/usr/bin/ld: Mainfile.c:(.text+0x10c): undefined reference to `func2_1'
/usr/bin/ld: Mainfile.c:(.text+0x114): undefined reference to `func2_2'
/usr/bin/ld: Mainfile.c:(.text+0x11c): undefined reference to `func3'
/usr/bin/ld: Mainfile.c:(.text+0x124): undefined reference to `func4_1'
/usr/bin/ld: Mainfile.c:(.text+0x12c): undefined reference to `func4_2'
/usr/bin/ld: Mainfile.c:(.text+0x134): undefined reference to `func5'
collect2: error: ld returned 1 exit status
make: *** [makefile:9: Mainfile] Error 1

似乎无法弄清楚它有什么问题.. 将我的 func c 文件及其头文件放在包含文件夹中,我将头文件包含在 Mainfile 中并测试它是否是我包含 c 文件的代码标题,然后它构建得很好。

有人知道我在 make 文件中做错了什么吗?第一次尝试链接这么多文件并使用 make 文件,非常感谢您的建议。

编辑:

我的主文件看起来像

#include "./Include/func_1.h" 
#include "./Include/func_2.h" 
... 
#include "./Include/func_5.h" 

in main()
{
    func1_1(argument);
    ... 
    func5_1(argument); 

    return 0; 
}

我的 func_1.h 文件看起来像

#ifndef FUNC_1_H
#define FUNC_1_H

// Argument check, is Host name and Port number default? 
static void func1_1(int argument);

#endif

那么 func_1.c 文件看起来像

#include "math.h"
#include "func_1.h"

static void func1_1(int argument)
{
    printf(argument + 1);
}

【问题讨论】:

  • 注意:所有gcc -c 命令都是无用的,它们会创建您不使用的.o 文件。如果你想使用 .o 文件然后告诉它链接 .o 文件而不是 .c 文件(这使它再次编译它们)
  • 显而易见的猜测是 func1_1、1_2、2_1、2_2、3、4_1、4_2 和 5 没有在任何地方定义。为什么不?您认为定义它们的代码在哪里?
  • 试过gcc -o Mainfile func_1.o func_2.o func_3.o func_4.o func_5.o Mainfile.o 还是一样的错误,而且所有的函数都定义在headers里面,然后在里面使用对应的c文件。
  • 你能创建一个minimal reproducible example吗?将其缩减为一两个显示问题的简短源文件,并将它们完整发布。听起来您在包含和链接之间存在某种奇怪的混淆(例如,将 .c 文件保留在 Include 目录中是不正常的),但从您的描述中很难准确判断您在做什么。
  • @Parko:如果你的意思是最后一条评论,那么这就是你的问题——你不应该在标题中定义你的函数,你应该只declare 在那里,实际上在 .c 文件中定义它们。

标签: c linux gcc makefile raspberry-pi


【解决方案1】:

你为什么要声明你的函数static,而你想在其他地方使用它们而不是在它们自己的文件中?删除所有这些 static 限定符,情况应该会好一些。

但如果我可以建议,你应该:

  1. 创建一个Src 目录并将所有*.c 文件移动到其中(是的,Mainfile.c 也是如此)。将它们存储在名为 Include 的目录中很奇怪。

  2. 改进您的 Makefile。以下是未经测试的起点:

     # Tell the compiler about the headers directory
     CFLAGS += -I./Includes
     # Find all C source files
     SRCS := $(wildcard Src/*.c)
     # Compute object file names from source file names
     OBJS := $(patsubst Src/%.c,%.o,$(SRCS))
    
     # Static pattern rule to tell make how to build an
     # object file from its source file
     $(OBJS): %.o: Src/%.c
         $(CC) $(CFLAGS) -c -o $@ $<
    
     # Tell make that `funcXX.o` depends on the `Includes/funcXX.h`
     # such that it rebuilds the former if the latter changes
     func_%.o: Includes/func_%.h
    
     # Tell make that `Mainfile.o` depends on all `Includes/funcXX.h`
     # files such that it rebuilds the former if any of the latter
     # changes
     Mainfile.o: $(wildcard Includes/func_*.h)
    
     # Tell make how to build the executable from the object files
     Mainfile: $(OBJS)
         $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
    

根据您显示的内容,技术上不需要在funcXX.c 中包含funcXX.h。您只需将它们包含在Mainfile.c 中。因此,如果您想删除项目,请删除这些包含语句以及:

func_%.o: Includes/func_%.h

来自 Makefile 的规则。但是,正如 cmets 中所指出的,即使不是严格需要它,它也可以检测声明和定义之间的不匹配。由你决定。

【讨论】:

  • funcXX.h 包含到funcXX.c 中有一个好处:如果您的声明和定义不匹配,则会被检测到。
  • @NateEldredge:你是对的。我从不这样做,但是是的,它有这个好处。我将更新我的答案以展示如何做到这一点。
  • 谢谢,明天我会努力让 makefile 变得更好,因为这里有点晚了。希望这将成为一个良好的基础,再次感谢。
【解决方案2】:
static void func1_1(int argument)

static 关键字导致该函数在其他模块(“翻译单元”)中不可见 - 这就是它的全部目的。 (见What does "static" mean in C?)。特别是符号func1_1 不会被设为全局,并且从其他模块中对该符号的引用也不会解析,正如您所见。

如果您想使用其他源文件中的函数,请在声明和定义中删除 static 关键字。

【讨论】:

  • 非常感谢!这解决了这个问题,现在我只需要查找如何使我的 makefile 更好,它会是一半体面。再次感谢。顺便说一句,我如何将其标记为已解决?
  • @Parko:您可以通过单击左侧的复选标记来接受答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-10
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多