2013-08-10 4 views
0

Итак, я пишу make-файл, который будет принимать некоторые файлы (* .in) в качестве ввода моей программы на C++ и сравнивать их вывод (results.out) с заданным корректным выводом (* .out). В частности, у меня есть файлы t01.in, t02.in, t03.in, t04.in и t05.in. Я проверил, что $ TESTIN = t01.in t02.in t03.in t04.in t05.in. Проблема заключается в том, что, по-видимому, он запускает блок% .in:% .out только для трех из этих файлов, 1,3 и 4. Почему он это делает?Makefile пропускает определенные зависимости

OUTPUT = chart 
COMPILER = g++ 
SOURCES = chart.cpp 
HEADERS = 
OBJS = $(SOURCES:.cpp=.o) 
TESTIN = tests/*.in 


all: $(OUTPUT) 

$(OUTPUT): $(OBJS) 
    $(COMPILER) *.o -o $(OUTPUT) 

%.o: %.cpp 
    clear 
    $(COMPILER) -c $< -o [email protected] 


test: $(TESTIN) 

%.in: %.out 
    ./$(OUTPUT) < [email protected] > tests/results.out 
    printf "\n" 
ifeq ($(diff $< tests/results.out),) 
    printf "\tTest of "[email protected]" succeeded for stdout.\n" 
else 
    printf "\tTest of "[email protected]" FAILED for stdout!\n" 
endif 

Кроме того, если есть лучший способ достижения того, что я пытаюсь сделать, или какие-либо другие улучшения, я мог бы сделать для этого Makefile (как я скорее новичок в этом), предложения будут высоко оценены.

EDIT: Если я добавлю вторую зависимость к блоку (% .in:% .out% .err), он запустит блок для всех пяти файлов. По-прежнему не знаю, почему это работает так, но не так.

+0

Это правило не делает много смысла , '% .in:% .out' означает« правило для ** создания ** 'foo.in' из' foo.out'. Но похоже, что у вас есть файлы '.in' * a priori *? –

+0

@OliCharlesworth Да, у меня уже есть .in-файлы. Как это следует переформулировать так, чтобы блок '% .in:% .out' выполнялся для каждого файла в' $ (TESTIN) ' –

ответ

1

Во-первых, Я не вижу, как TESTIN может быть правильным. Эта строка:

TESTIN = tests/*.in 

недействительный шаблон в Make; он должен указать переменную TESTIN значение tests/*.in. Но давайте предположим, что оно имеет значение t01.in t02.in t03.in t04.in t05.in или tests/t01.in tests/t02.in tests/t03.in tests/t04.in tests/t05.in, или где бы они ни находились.

Во-вторых,, как @OliCharlesworth указывает, это правило:

%.in: %.out 
    ... 

является правилом для создания * .в файлов, которые не то, что вы собираетесь. А почему он работает несколько тестов, а не другие, вот моя теория:

Отметка t01.out позже, чем t01.in, так что решает, что он должен «восстановить» t01.in; также t03.in и t04.in. Но временная метка t02.out выше, чем у t02.in, поэтому Make не пытается «перестроить» t02.in; также t05.in. Временные метки t02.err и t05.err приведены ниже, чем у t02.in и t05.in соответственно, поэтому, когда вы добавляете предварительное условие %.err, Make запускает все тесты. Вы можете проверить эту теорию, проверив отметки времени и поэкспериментируя с touch.

В любом случае, давайте перепишем его. Нам нужна новая цель для нового правила:

TESTS := $(patsubst %.in,test_%,$(TESTIN)) # test_t01 test_t02 ... 

.PHONY: $(TESTS) # because there will be no files called test_t01, test_t02,... 

$(TESTS): test_%: %.in %.out 
    ./$(OUTPUT) < $< > tests/results.out 

Теперь для условного. Вы выполнили условие в синтаксисе Make; Make будет оценивать его до выполнения какого-либо правила, поэтому tests/result.out еще не существует, а переменные, такие как $<, еще не определены. Мы должны поставить условную внутри команды, в синтаксисе оболочки:

$(TESTS): test_%: %.in %.out 
    ./$(OUTPUT) < $< > tests/results.out 
    if diff $*.out tests/results.out >/dev/null; then \ 
    echo Test of $* succeeded for stdout.; \ 
    else echo Test of $* FAILED for stdout!; \ 
    fi 

(Обратите внимание, что только первая линия условного должна начинаться с TAB.)

+0

Вы в точности относитесь к' TESTIN', и я исправил это. Также ваша теория временных меток кажется правильной. Теперь я попытаюсь понять вашу переписку. Спасибо. –

+0

Вероятно, вы также должны «вывести $$?» В ветку 'else', чтобы Make был осведомлен об ошибке' diff'. Еще лучше, просто пропустите условное и просто запустите 'diff' -' echo' просто обновляет информацию, которая уже была напечатана, и поэтому не помогает знающему пользователю. – tripleee

+0

@ tripleee: Вы имели в виду, что обратились к своему комментарию к OP? – Beta

Смежные вопросы