Почему моя цель всегда перекомпилирует исполняемый файл, даже если в коде ничего не изменилось? - PullRequest
3 голосов
/ 04 мая 2019

Я почти новичок в написании 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

Например, когда я печатаю

make future

в первый раз, когда я все скомпилировал:

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

Если я ничего не изменяю в коде и сразу же набираю «сделать будущее», я ожидаю что-то вроде «ничего не будет сделано для ...». Но вместо этого я получаю:

nvcc -std=c++14 -g -DMEASURES -Iinclude/  bin/main_cos.o bin/farmkernels.o bin/cudaUtils.o -o bin/future.out

Ответы [ 2 ]

5 голосов
/ 04 мая 2019

Вы специально сказали make всегда перестраивать без учета временных меток зависимости:

.PHONY: future managed stream clean

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 $@

(также используются автоматические переменные по принципу «Не повторяйся»)

2 голосов
/ 04 мая 2019

Почему цель всегда перекомпилируется?

Вы указали, что future является «фальшивой целью».Это означает, что:

  • future не соответствует фактическому файлу, то есть
  • Нет даты с датой, которую Make может проверить, чтобы определить, истекло ли значение futureна сегодняшний день, поэтому
  • future никогда не может быть обновленным, поэтому
  • Всякий раз, когда вы строите future, вы должны выполнить для него команды

И ваша команда связывания указана под целью future;поэтому каждый раз он запускается заново.

Более подробное объяснение о .PHONY см. Какова цель .PHONY в make-файле?

Почему вы можете это сделать

Два варианта:

  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
    
...