【问题标题】:"File or folder not found" after manually compiling and linking with make手动编译并与make链接后“找不到文件或文件夹”
【发布时间】:2019-03-17 01:31:07
【问题描述】:

我们有创建一个makefile的练习,它应该“创建一个项目bbfoobbfoo是从barbaz和foo。barbaz 是从 barbaz 链接的。使用编译器 cc (这是我的 gcc system) 和链接器 ld。"

我创建了三个简单的 c 文件:

bar.c:

int one() {
    return 1;
}

baz.c:

int two() {
    return 2;
}

foo.c

#include <stdio.h>

int main() {
    printf("bar: %d\n", one());
    printf("baz: %d\n", two());
    return 0;
}

以及下面的makefile:

bar: bar.c
    cc -c -g -o bar.o bar.c
baz: baz.c
    cc -c -g -o baz.o baz.c
barbaz: bar baz
    ld -shared -o barbaz.o bar.o baz.o
foo: foo.c
    cc -c -g -Wno-implicit-function-declaration -o foo.o foo.c
bbfoo: barbaz foo
    ld -lc --entry=main -o bbfoo.out barbaz.o foo.o

$ 制作 bbfoo

正常工作并创建相应的文件。但是当我尝试使用

运行项目时

$ ./bbfoo.out

它显示“找不到文件或文件夹”。

当我使用 gcc 时它完美无缺:

$ gcc -o bbfoo.out bar.c baz.c foo.c

$ ./bbfoo.out

栏:1

baz: 2

我的错误是什么?甚至可以链接这样的项目(分两步)?

【问题讨论】:

  • 一般来说,使用 makefile 规则创建一个名称与规则目标不同的文件是不正确的。您有一个目标名称bbfoo,但您的配方实际上创建了文件bbfoo.out。您的规则应创建bbfoo(将您的配方更改为使用-o bbfoo),否则目标名称也应为bbfoo.out
  • 感谢您的信息。我想这也是其他目标的情况吗?但这是一种形式,它可能不会改变功能。
  • 发布的项目架构缺少每个子文件的头文件。然后它缺少那些头文件的#include 语句

标签: c gcc makefile ld cc


【解决方案1】:

您的 makefile 使用 ld 链接,但您的 gcc 示例使用编译器驱动程序链接。你也应该这样做:

bbfoo: barbaz foo
    gcc -o bbfoo.out barbaz.o foo.o

编译器驱动程序可能(在您的情况下显然是)包含一堆特定于系统的东西,使您的程序实际工作。通常不建议尝试直接运行链接器。

如果您想查看它真正使用的链接行是什么,您可以使用 GCC 的 -v 标志,如果需要,也可以将标志复制到您的 makefile 中。但是,您有可能在未来无法获得重要的变化。

【讨论】:

  • 嗯,这只是一个练习,而不是一个真正的项目。但是对于这个练习,我们应该直接使用链接器。我会看看 GCC 使用的标志,谢谢你的提示。
  • 您的共享库也可能没有被正确提取。检查默认搜索路径是什么以及为什么会在链接器/编译器/加载器文档中发生这种情况。
  • 我不认为这是问题所在,因为当我对最后一个 ld 不使用 -lc 参数时,我得到一个错误(“未定义对 printf 的引用”)。还是你的意思是别的?
【解决方案2】:

如果你使用 make 你应该坚持它的基本原则,我们可以总结为:

FILE-to-create: files-used-to-create-FILE
    shell-commands-that-create-FILE

这是非常重要的,因为 make 会比较文件的最后修改时间来决定哪些是过时的,哪些是最新的。这不是一种形式,它确实改变了功能。所以,在你的情况下,你应该有:

bar.o: bar.c
    cc -c -g -o bar.o bar.c

baz.o: baz.c
    cc -c -g -o baz.o baz.c

foo.o: foo.c
    cc -c -g -Wno-implicit-function-declaration -o foo.o foo.c

barbaz.so: bar.o baz.o
    ld -shared -o barbaz.so bar.o baz.o

bbfoo: barbaz.so foo.o
    ld -lc --entry=main -o bbfoo barbaz.so foo.o

请注意,make 有一些很好的功能可以帮助分解这种简单的规则集。比如,automatic variables ($@, $^...), implicit rules (例如用于从*.c 源文件构建*.o 目标文件), implicit variables used by the implicit rules (CFLAGS, @ 987654332@...)、target-specific variable values(查看CFLAGS 声明为foo.o)等等。示例:

CFLAGS := -g

foo.o: CFLAGS += -Wno-implicit-function-declaration

barbaz.so: bar.o baz.o
    $(LD) -shared -o $@ $^

bbfoo: barbaz.so foo.o
    $(LD) -lc --entry=main -o $@ $^

是的,对目标文件没有任何规则,make 已经知道如何构建它们。

【讨论】:

  • 感谢您的回答。通过这个陈述,我的意思是这不是我错误的原因。即使我同意你的版本更短、更清晰、更容易更改,但它并不能解决我的问题。当我尝试像以前一样运行它时收到相同的错误消息。
  • 如果您输入file bbfoo,您会看到什么?您看到的是否是您计算机体系结构的二进制文件?还是用于其他架构?
  • 我在 WSL 上使用 Ubuntu,但使用“真正的”linux,输出是相似的。 bbfoo: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=a6d0029a96c8384ad525db45cac70d8df77b3052, not stripped
【解决方案3】:

贴出的代码有很多不足之处。

建议:

bar.h

#ifndef BAR_H
#define BAR_H
int one( void );
#endif

bar.c:

#include "bar.h"
int one() {
    return 1;
}

baz.h

#ifndef BAZ_H
#define BAZ_H
int one( void );
#endif

baz.c:

#include "baz.h"
int two() {
    return 2;
}

foo.c

#include <stdio.h>
#include "bar.h"
#include "baz.h"

int main( void ) {
    printf("bar: %d\n", one());
    printf("baz: %d\n", two());
    return 0;
}

makefile.mak

.PHONY all
all: bbfoo.out

bar: bar.c bar.h
    cc -c -g -o bar.o bar.c -Ibar.h

baz: baz.c baz.h
    cc -c -g -o baz.o baz.c -Ibaz.h

libbarbaz.so: baz.o bar.o
    ld -shared -o libbarbaz.so bar.o baz.o    

foo: foo.c baz.h bar.h
    cc -c -g -Wno-implicit-function-declaration -o foo.o foo.c -Ibar.h -Ibaz.h

bbfoo.out:  foo.o libbarbaz.so
    ld -lc --entry=main -o bbfoo.out foo.o -lbarbaz

使用make 中的快捷变量会大大缩短这个makefile,但会使它更加神秘

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多