为什么即使代码没有任何变化,我的目标也总是重新编译可执行文件?

Mar*_*ara 3 linux rebuild cuda makefile

我写Makefile几乎是新手,对可能出现的小错误感到抱歉。即使源代码没有任何变化,我的Makefile仍会继续重新编译可执行文件(.out)。目标对其他对象有一些依赖性。无论如何,这些对象不会重新编译相对的源文件(就像应该的那样)。那么,为什么目标重新编译.out文件呢?

任何其他建议将不胜感激。

# -*- Makefile -*-

CC:= nvcc
CFLAGS:= -std=c++14 -g -DMEASURES
ALLFLAGS:= $(CFLAGS) -Iinclude/ 
LOWPAR:= $(ALLFLAGS) -DLOWPAR


BIN:=bin/
SRC:=src/
INCLUDE:=include/


.PHONY: future managed stream clean

####DEVICE####
#cos future, stream, managed
future: $(BIN)main_cos.o $(BIN)farmkernels.o $(BIN)cudaUtils.o
    $(CC) $(ALLFLAGS) $(BIN)main_cos.o $(BIN)farmkernels.o $(BIN)cudaUtils.o -o $(BIN)future.out

managed: $(BIN)main_cos.o $(BIN)farmkernels.o $(BIN)cudaUtils.o
    $(CC) $(ALLFLAGS) $(BIN)main_cos.o $(BIN)farmkernels.o $(BIN)cudaUtils.o -o $(BIN)managed.out

stream: $(BIN)main_cos.o $(BIN)farmkernels.o $(BIN)cudaUtils.o
    $(CC) $(ALLFLAGS) $(BIN)main_cos.o $(BIN)farmkernels.o $(BIN)cudaUtils.o -o $(BIN)stream.out


$(BIN)main_cos.o: $(SRC)main_cos.cpp $(INCLUDE)cosFutStr.h $(INCLUDE)cudaUtils.h
    $(CC) $(ALLFLAGS) -c $(SRC)main_cos.cpp -D$(shell echo $(MAKECMDGOALS) | tr a-z A-Z) -o $(BIN)main_cos.o

$(BIN)farmkernels.o:  $(SRC)farmkernels.cu $(INCLUDE)cosFutStr.h $(INCLUDE)cudaUtils.h
    $(CC) $(ALLFLAGS) -c $(SRC)farmkernels.cu -o $(BIN)farmkernels.o

$(BIN)cudaUtils.o: $(SRC)cudaUtils.cpp  $(INCLUDE)cudaUtils.h
    $(CC) $(ALLFLAGS) -c $(SRC)cudaUtils.cpp -o $(BIN)cudaUtils.o

####clean####
clean:
    rm -f $(BIN)*.o 
    rm -f $(BIN)*.out
Run Code Online (Sandbox Code Playgroud)

例如当我输入

make future
Run Code Online (Sandbox Code Playgroud)

第一次编译所有内容:

nvcc -std=c++14 -g -DMEASURES -Iinclude/  -c src/main_cos.cpp -DFUTURE -o bin/main_cos.o
nvcc -std=c++14 -g -DMEASURES -Iinclude/  -c src/farmkernels.cu -o bin/farmkernels.o
nvcc -std=c++14 -g -DMEASURES -Iinclude/  -c src/cudaUtils.cpp -o bin/cudaUtils.o
nvcc -std=c++14 -g -DMEASURES -Iinclude/  bin/main_cos.o bin/farmkernels.o bin/cudaUtils.o -o bin/future.out
Run Code Online (Sandbox Code Playgroud)

如果我不更改代码中的任何内容并立即重新键入内容以创造未来,那么我希望诸如“什么都不做……”之类的东西。但是我得到的是:

nvcc -std=c++14 -g -DMEASURES -Iinclude/  bin/main_cos.o bin/farmkernels.o bin/cudaUtils.o -o bin/future.out
Run Code Online (Sandbox Code Playgroud)

Ben*_*igt 5

您明确要求make始终在不考虑依赖项时间戳的情况下进行重建:

.PHONY: future managed stream clean
Run Code Online (Sandbox Code Playgroud)

make 在做你所要求的。


如果您想要不错的命名目标而不引起重建,请不要为命名目标编写规则。相反,给他们依赖。正如您已经注意到的那样,.PHONY它并不强制重建所有依赖关系,它仅运行直接规则。

.PHONY: future managed stream clean

future: $(BIN)future.out

$(BIN)future.out: $(BIN)main_cos.o $(BIN)farmkernels.o $(BIN)cudaUtils.o
    $(CC) $(ALLFLAGS) $+ -o $@
Run Code Online (Sandbox Code Playgroud)

(也根据“不要重复自己”的原则使用自动变量)


ein*_*ica 5

为什么目标总是重新编译?

您已表明这future是一个“虚假目标”。这意味着:

  • future与实际文件不对应,即
  • 没有任何日期可以让 Make 检查以确定是否future是最新的,因此
  • future永远不可能是最新的,因此
  • 每当您构建时future,您都必须执行它的命令

并且您的链接命令列在future目标下;所以每次都会重新运行。

有关 的更深入解释.PHONY,请参阅:Makefile 中 .PHONY 的用途是什么?

你能做些什么

两种选择:

  1. 使用文件目标。你的future目标的命令会生成$(BIN)future.out,对吧?因此,将其替换为$(BIN)future.out目标,然后构建它。

  2. 添加一个$(BIN)future.out目标,但为了方便起见,不要直接构建它 - 让future目标依赖于它,就像 @BenVoigt 建议的那样:

     .PHONY: future other_pho ny_target s_here
    
     future: $(BIN)future.out
    
     $(BIN)future.out: $(BIN)main_cos.o $(BIN)farmkernels.o $(BIN)cudaUtils.o
         $(CC) $(ALLFLAGS) $(BIN)main_cos.o $(BIN)farmkernels.o $(BIN)cudaUtils.o -o $(BIN)future.out
    
    Run Code Online (Sandbox Code Playgroud)

  • @MariaChiaraCecconi:不存在“未来永远不可能是最新的”这样的“规则”。它不是规则,而是您设计的结果。您永远不会创建名为“future”的文件,因此没有文件时间戳。因此,当`make`比较文件时间戳时,它发现“future”缺失,需要重建。`.PHONY` 另外会导致时间戳被忽略(如果有的话)(也就是说,也没有“虚假目标与实际文件不对应”的规则),尽管与实际文件不对应的目标应该是虚假的,则不需要相反的情况。 (2认同)