Как написать разные неявные правила для разных имен файлов для GNU Make - PullRequest
1 голос
/ 15 июня 2010

У меня есть каталог, в который я продолжаю добавлять различные исходные файлы C ++ и общий Makefile для их компиляции. Это содержимое Makefile:

.PHONY: all clean

CXXFLAGS = -pipe -Wall -Wextra -Weffc++ -pedantic -ggdb

SRCS = $(wildcard *.cxx)
OBJS = $(patsubst %.cxx,%.out,$(SRCS))

all: $(OBJS)

clean:
    rm -fv $(OBJS)

%.out: %.cxx
    $(CXX) $(CXXFLAGS) $^ -o $@

ПРИМЕЧАНИЕ. Как видно из приведенного выше, я использую * .out для расширений исполняемых файлов (а не для объектных файлов).

Также, есть несколько файлов, которые скомпилированы вместе:

g++ file_main.cxx file.cxx -o file_main.out

Для компиляции таких файлов до сих пор я добавлял явные правила в Makefile:

file_main.out: file_main.cxx file.cxx

file.out: file_main.out
    @echo "Skipping $@"

Но теперь мой Makefile имеет много явных правил, и я хотел бы заменить их на более простое неявное правило.

Есть идеи, как это сделать?

Ответы [ 2 ]

4 голосов
/ 17 июня 2010

Во-первых, этот метод компиляции нескольких исходных файлов непосредственно в исполняемый файл не очень хорошая идея.Более распространенный подход compile-then-link избавит от ненужной компиляции.

Тем не менее, способ замены многих явных правил более простым правилом зависит от того, что общего у явных правил.У вас уже есть шаблонное правило:

%.out: %.cxx
    $(CXX) $(CXXFLAGS) $^ -o $@

, и если все, что вы хотите сделать, это добавить другой исходный файл к определенной цели, вам не нужно делать это:

g++ file_main.cxx file.cxx -o file_main.out

Вы можете получить эффект, просто добавив необходимое условие (отдельной строкой):

file_main.out: file.cxx

Если у вас есть несколько целей с этим шаблоном, вы можете использовать правило шаблона:

file_main.out another_main.out a_third_main.out: %_main.out : %.cxx

Если у вас много таких целей, вы можете использовать переменную:

MAIN_THINGS = file another a_third a_fourth and_yet_another
MAIN_TARGETS = $(addsuffix _main.out, $(MAIN_THINGS))
$(MAIN_TARGETS): %_main.out : %.cxx

И вы можете добавить другие шаблоны для других наборов целей, даже перекрывающихся наборов.Это охватывает вашу ситуацию?

1 голос
/ 15 июня 2010

Кажется, что вы помещаете исходный код для нескольких различных программ в одну папку, и это действительно источник ваших проблем.Если вы разделяете исходный код для своих библиотек и программ на отдельные папки (или, что еще лучше, на отдельные проекты), то вы можете обойти эту проблему в зависимости от всех исходных файлов в данной папке.Когда все смешано, необходимо быть явным.

Тем не менее, если ваши зависимости имеют непротиворечивые, предсказуемые имена, то можно устранить эту избыточность с помощью eval-функции ,Например, на основе приведенного выше примера:

#
# I'm going to use standard file extensions here,
# slightly deviating from your conventions. I am also
# assuming that there is a variable named PROGNAMES,
# which gives a list of all the programs to be built.
#
define ADD_EXECUTABLE
     $(1): $(1).o $(1)_main.o
         $(LINK.cc) $(1).o $(1)_main.o -o $(1)
endef

$(foreach progname,$(PROGNAMES),$(eval $(call ADD_EXECUTABLE,$(progname)))) 

Кроме того, всего несколько предложений ... вы должны добавить CXXFLAGS вместо того, чтобы перезаписывать его, и вам лучше использовать стандартные расширения файлов (".cpp«для исходных файлов C ++,« .o »для объектных файлов, без расширения для исполняемых файлов).См. Мое руководство по Makefile для получения советов по упрощению работы с Make (без каламбура).

...