手动编译并与make链接后,“找不到文件或文件夹”

时间:2018-10-11 21:12:04

标签: c gcc makefile ld cc

我们已经进行了一个创建文件的练习,该文件应“创建一个项目 bbfoo bbfoo 是从 barbaz 和< em> foo 。 barbaz bar baz 链接。使用编译器cc (在我的计算机上是gcc系统)和链接程序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
  

$ make bbfoo

正常运行,并且创建了相应的文件。但是当我尝试使用

运行项目时
  

$ ./bbfoo.out

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

当我使用gcc时,它可以完美地工作:

  

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

     

$ ./bbfoo.out

     

栏:1

     

巴兹:2

我怎么了?甚至可以(两个步骤)链接这样的项目吗?

3 个答案:

答案 0 :(得分:1)

您的makefile使用ld进行链接,但是您的gcc示例使用编译器驱动程序进行链接。您应该执行相同的操作:

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

编译器驱动程序可能会(而且您的情况确实如此)包括一堆特定于系统的内容,这些内容可使您的程序实际运行。通常不建议尝试直接运行链接器。

如果要查看其实际使用的链接行,则可以使用GCC的-v标志,如果需要,也可以将其从标志复制到makefile中。但是,这样一来,您就有可能在将来无法进行重要的更改。

答案 1 :(得分:0)

如果使用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(例如,用于从*.o源构建*.c对象文件文件),implicit variables used by the implicit rulesCFLAGSLD ...),target-specific variable values(查看CFLAGS的{​​{1}}声明)等等。示例:

foo.o

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

答案 2 :(得分:0)

发布的代码存在很多缺点。

建议:

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,但会使它变得更加隐秘