我的Makefile文件编译所有的文件,每次我运行它虽然文件没有改变。我知道,这个问题已经被问了几次,但没有提供的解决方案似乎为我工作。我是新来的和makefile大多数时候我不明白,在解决方案中使用的术语。另外,我想所有生成的.o文件保存的文件夹下的“OBJ”
这里是我的文件夹结构
project (-)
gen (-)
display (-)
.c and .h files
logic (-)
.c and .h files
lib (-)
include (-)
.h files
.lib files
man (-)
.c and .h files
obj (-)
want to save all the .o files here
我使用的MinGW在Windows操作系统上运行此
这里是我的Makefile:
ALL: demo
SRCS:= filename1.o filename2.o filename3.o filename4.o and so on till filename27.o
demo: display.o logic.o man.o
gcc $(SRCS) -lglut32 -loglx -lopengl32 -Llib -o demo
display.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/display/*.c -lglut32 -loglx -lopengl32 -Llib -c
logic.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/logic/*.c -lglut32 -loglx -lopengl32 -Llib -c
man.o:
gcc -Igen/display -Igen/logic -Iman -Ilib/include man/*.c -lglut32 -loglx -lopengl32 -Llib -c
clean:
@echo "Cleaning up.."
-rm -rf *.o
-rm *.exe
注:过剩和oglx文件存在lib文件夹中。 Display.o,lib.o和man.o没有相应的.c文件。他们是在他们许多的C文件只是文件夹名称。
我理解这可能是问题。由于没有display.o,logic.o创造man.o文件,请遵从它eveytime相关联的规则。让我怎么告诉它来检查实际的.o filename1.o,filename2.o等的时间戳和重新编译,只有当他们比相应的C文件和h文件日期早的甚至它们所依赖的LIB文件。
我尝试以下创建的依赖,避免每次文件的编制。但是,这并没有帮助。
%.d: %.c
@set -e; rm -f $@; \
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
在一个基本水平,make
正在寻找像行:
target: dependency
command
如果target
不存在,它要求dependency
规则,然后运行command
。如果target
确实存在,它测试,如果dependency
是新的或不存在。如果是这样,它要求dependency
规则,然后运行command
。否则,它停止。
显著,为dependency
规则将仅在(一)dependency
不存在,或(b)dependency
比target
新的调用。
在这个问题中,假设我们运行make demo
。然后make
查找开头demo:
并注意到它声明了依赖行。因此,它看起来在每个反过来依赖,看看他们是否需要采取行动。它首先发现display.o
。它注意到display.o:
不存在,所以它运行的相关规则。它为其他*.o
相同。
为了避免总是被运行,因为没有相关的文件存在*.o
规则,你可以重写,如:
ALL: demo
SRCS:= filename1.o filename2.o filename3.o filename4.o and so on till filename27.o
demo: display.ts logic.ts man.ts
gcc $(SRCS) -lglut32 -loglx -lopengl32 -Llib -o demo
display.ts: gen/display/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/display/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > display.ts
logic.ts: gen/logic/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include gen/logic/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > logic.ts
man.ts: man/*.c
gcc -Igen/display -Igen/logic -Iman -Ilib/include man/*.c -lglut32 -loglx -lopengl32 -Llib -c
echo . > man.ts
clean:
@echo "Cleaning up.."
-rm -rf *.o *.ts
-rm *.exe
问题是,你的二进制对象的目标(如display.o
)实际上不匹配他们的规则生成的文件。如果你告诉make
它需要使目标display.o
,它(通常,除了伪目标,但那些始终重新运行),预计该规则的配方来生产相应的文件,如果目标需要返工它可以跟踪。如果没有这样的文件被产生,这个目标始终评估为过时和需要重塑。
这样一个愚蠢的例子的位将是以下三种:
.
├── Makefile
├── main.c
└── test
└── file.c
和Makefile:
main: test.o main.o
$(CC) -o main *.o
test.o:
$(CC) $(CFLAGX) -c test/*.c
没有test.o
文件和目标需要返工......的规则运行,(再)产生file.o
。由于此的目标是重拍,是main
前提...一切总是被重拍。
现在有了这个小改动:
main: test.o main.o
$(CC) -o main *.o
test.o:
$(CC) $(CFLAGX) -o $@ -c test/*.c
test.o
目标确实产生test.o
文件和规则不需要再造如果test.c
不会改变......与test.o
不变,main.c
或许还有,我们得到:
$ make
make: 'main' is up to date.
它仍然是不完全正确的,因为它确实应该阅读:
main: test.o main.o
$(CC) -o main $+
test.o: test/*.c
$(CC) $(CFLAGX) -o $@ -c $^
当我宣布取决于test.o
的先决条件,并在规则的食谱自动变量引用他们和目标。和同去的先决条件链接。当然,在这个简单的例子,我可以只依靠隐含模式规则和做到这一点:
main: test/file.o main.c
test/file.o: test/*.c
这是什么意思为您的makefile?当您编译目标文件,看看他们是怎么实际产生和你的目标到或匹配(与-o $@
例如)告诉他们产生精确匹配您的目标文件。
我已经延长了愚蠢的例子了一下,现在有在test/
两个文件:
.
├── Makefile
├── main.c
└── test
├── file.c
└── other.c
和Makefile文件可以是这个样子:
main: obj/file.o obj/other.o main.c
obj/%.o: test/%.c
mkdir -p obj
$(CC) $(CFLAGS) -c -o $@ $^
现在存储对象中obj/
文件,并仍然明白什么需要的东西,可以跟踪更改。当然,你的设置更复杂,将需要更多的规则,或许也是占卜实际源或中介目标从目录树,并定义几个变量与信息,e.g工作:
OBJS := $(patsubst test/%.c,obj/%.o,$(wildcard test/*.c))
main: $(OBJS) main.c
obj/%.o: test/%.c
mkdir -p obj
$(CC) $(CFLAGS) -c -o $@ $^
但原理是相同的。