2015-08-22 2 views
0

Я пытаюсь создать автономный файл Makefile. Мои Makefile есть правило, как следующий:Сделать цель зависит от того же предпосылки с разными флагами

benchmark: 
     (something that depends on variable CXX) 

Это правило представляет собой единую точку отсчета для одного компилятора. Я хочу сравнить несколько компиляторов.

Так что я хотел бы выполнить это следующий, не прибегая к $(MAKE) рекурсивно внутри правила участка (псевдо-синтаксис):

plot: benchmark CXX=clang++ benchmark CXX=g++ 
    (generate a plot) 

А именно, я хочу, эта цель зависит от предварительных требований теста + один флаг и рассматривать как два разных предпосылки, даже если они являются одним и тем же правилом.

+0

Почему вы против рекурсивного вызова? Как вы планируете обеспечить, чтобы все файлы объектов были перестроены каждый раз с помощью правильного компилятора, а также связанная с ним программа? Я думаю, вы направились в неправильном направлении, но я не совсем уверен, как отправить вас в правильном направлении. Возможно, вам нужен каталог «benchmark-1» (sub-), где вы создаете исполняемый файл для 'g ++' и 'benchmark-2' (подкаталог), где вы создаете исполняемый файл для' clang ++ '.Источник может исходить из исходного (родительского) каталога - возможно, через VPATH. Но я этого не пробовал. _ [... продолжение ...] _ –

+0

_ [... продолжение ...] _ То, что я обычно делаю, это 'make clean; сделать тест CXX = g ++; чистить; сделать тест CXX = g ++; сделать чистым' или что-то подобное. Окончательный 'make clean' гарантирует, что следующая сборка ведет себя правильно, независимо от последовательности или успеха предыдущих операций. –

ответ

1

Предполагая, что GNU Make, я думаю, что логика вы ищете может быть выражена следующим образом:

CXXES := clang++ g++ 

benchmark: $(CXXES:%=benchmark-%) 

Тогда есть одно правило для создания контрольных показателей:

benchmark-%: 
    # generate a plot using $(CXX), which will be equal to [email protected] 

или несколько если правила генерации вашего графика являются специфическими для компилятора:

benchmark-clang++: CXX = clang++ 
    # generate a plot using $(CXX) 
    (...) 

benchmark-g++: CXX = g++ 
    # generate a plot using $(CXX) 
    (...) 

Было бы лучше идентифицировать fy выходные файлы (графики?), имена файлов которых зависят от значения $(CXX) и использовать их в качестве промежуточных целей.

+0

Как должна работать линия зависимости? Разве они не означают, что 'make' пытается сделать файлы' CXX', '=' и либо 'clang ++', либо' g ++', и, вероятно, сработает? Вы можете быть зародышем идеи - отдельно названные цели, которые создают исполняемый файл с использованием разных компиляторов. Но объектные файлы нужно переименовать. У меня такое чувство, что оно волосатое. –

+0

@Jonathan Leffler: Я на самом деле не пробовал это, но идея указывать цели с конкретными значениями '$ (CXX)' в их именах и иметь общую (фальшивую) цель, зависит от всех из них. Эта идея должна работать, даже если детали этой конкретной реализации не окажутся (в этом случае этот ответ должен быть исправлен). – reinierpost

+0

Проблема в том, что это два компилятора. Я не могу полагаться на статическое правило, подобное этому. Правило должно быть чем-то вроде эталона - $ {COMPILER} –

1

Как вы можете предложить reinierpost, вы можете определить псевдо-цель для каждого из ваших компиляторов. Псевдо-цель - это цель, не связанная с ней.

Но поскольку make действительно доволен действительными файловыми целями (цели считаются актуальными или не основаны на их последней дате изменения), вы также можете использовать результат своего сюжета в качестве цели. И, как также было предложено, вы можете обернуть все это в конструкцию foreach - eval - call, чтобы разложить ваш код. Что-то вроде:

COMPILERS = clang++ g++ 

define PLOT_compiler 
plotfile-$(1): CXX = $(1) 
plotfiles += plotfile-$(1) 
endef 

$(foreach compiler,$(COMPILERS),$(eval $(call PLOT_compiler,$(compiler)))) 

all: $(plotfiles) 

plotfile-%: 
    <generate plot file using the CXX variable> 

foreach - eval - call конструкция конкретизирует один набор делать заявления за компилятором, как это определено в переменной PLOT_compiler.

Если вы предпочитаете собирать все результаты в одном файле с именем, скажем, plots.txt вы можете вместо этого использовать:

COMPILERS = clang++ g++ 

define PLOT_compiler 
plotfile-$(1): CXX = $(1) 
plotfiles += plotfile-$(1) 
endef 

$(foreach compiler,$(COMPILERS),$(eval $(call PLOT_compiler,$(compiler)))) 

plots.txt: $(plotfiles) 
    cat $(plotfiles) > [email protected] 

plotfile-%: 
    <generate plot file using the CXX variable> 

clean: 
    rm -f $(plotfiles) 

ultraclean: 
    rm -f $(plotfiles) plots.txt 

В clean и ultraclean цели поможет вам держать ваше рабочее место в чистоте. Вы можете легко проверить все это, заменив <generate plot file using the CXX variable> рецепт на echo $(CXX) > [email protected], а также:

make 
make clean 
cat plots.txt 
+0

Я хочу один сюжет для всех результатов :) Он разделен на разделы для каждого компилятора. Сравнивает два бинарных файла для каждого компилятора. Так что это не соответствует тому, что я хочу. Я подумал, что, возможно, это даже несовместимо: у меня есть что-то вроде CXX, которое всегда работает для каждого компилятора. Но результат, который я хочу, требует компиляции несколько раз. Таким образом, я получаю своего рода «конфликт», где для построения файлов, которые мне нужно скомпилировать для разных CXX, но мне нужен только один файл графика. –

+0

Это не проблема. Если вы знаете, как добавить новый раздел в существующий файл сюжета, вы можете использовать пустые файлы в качестве целей. Просто закончите свой рецепт с помощью 'touch $ @', и все готово. –

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