我们已经进行了一个创建文件的练习,该文件应“创建一个项目 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
我怎么了?甚至可以(两个步骤)链接这样的项目吗?
答案 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 rules(CFLAGS
,LD
...),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,但会使它变得更加隐秘