Определить пользовательскую функцию gmake, эквивалентную нескольким конвейерным функциям - PullRequest
0 голосов
/ 03 декабря 2018

Я пытаюсь определить функцию, которая будет работать с $(patsubst %,$(OBJDIR)/%.o,$(basename $(ARG1)))

что-то вроде;

define getobj
    $(1): $(patsubst %,$(OBJDIR)/%.o,$(basename $(1)))
endef

контекст, который я пытаюсь улучшить:

OBJDIR = objects
TESTHNF_CPPS = testhnf.cpp timings.cpp LongModular.cpp VeryLong.cpp VeryLongModular.cpp squfof.cpp
TESTHNF_CS = mt19937int.c lip.c
TESTHNF_OBJS = $(patsubst %,$(OBJDIR)/%.o,$(basename $(TESTHNF_CPPS) $(TESTHNF_CS)))
TESTHNF_OBJS2 = $(getobj $(TESTHNF_CPPS) $(TESTHNF_CS))

Здесь $(TESTHNF_OBJS2) остается пустым.Как мне написать функцию?

1 Ответ

0 голосов
/ 03 декабря 2018

Ваш макрос getobj выглядит так, как будто вы хотите объявить правило (target: prerequisites).Но использование, которое вы пытаетесь использовать, выглядит так, как будто вы пытаетесь присвоить результат его расширения переменной, что на самом деле не имеет смысла.

Итак, давайте проигнорируем правило просмотра и сосредоточимся на вашей цели (насколько я понимаю): определите макрос, который получает basename каждого слова, которое ему передано, и заменяет его на $(OBJDIR)/<basename>.o.Вы были почти там:

getobj = $(patsubst %,$(OBJDIR)/%.o,$(basename $(1)))

должен сделать это, где $(1) - это параметр макроса, список слов, разделенных пробелами.И вы вызываете его с помощью call make-функции :

TESTHNF_OBJS2 = $(call getobj,$(TESTHNF_CPPS) $(TESTHNF_CS))

call make-функция заменяет $(1) на параметр $(TESTHNF_CPPS) $(TESTHNF_CS) в определении getobjи возвращает результат.В вашем случае это эквивалентно:

TESTHNF_OBJS2 = $(patsubst %,$(OBJDIR)/%.o,$(basename $(TESTHNF_CPPS) $(TESTHNF_CS)))

Когда TESTHNF_OBJS2 будет расширен, результат будет:

objects/testhnf.o objects/timings.o ... objects/lip.o

Вернуться к просмотру правила.Если вместо этого вам нужно создать правило make:

<basename>: $(OBJDIR)/<basename>.o

для каждого <basename> в вашем списке, плюс определить переменную TESTHNF_OBJS, в которой перечислены все соответствующие объектные файлы, то вы можете использовать комбинациюforeach, eval и call.Но все немного сложнее, потому что make один раз расширяет параметр eval, создает экземпляр результата как конструкцию make и расширяет ее еще раз при синтаксическом анализе как любые обычные конструкции make.Таким образом, двойное расширение иногда следует избегать путем удвоения знаков $;это не ваш случай, но лучше помнить об этом при использовании подобных вещей.

OBJDIR = objects
TESTHNF_CPPS = testhnf.cpp timings.cpp LongModular.cpp VeryLong.cpp VeryLongModular.cpp squfof.cpp
TESTHNF_CS = mt19937int.c lip.c
TESTHNF_OBJS :=

# $(1): basename of one source file
define getobj
    $(1): $(OBJDIR)/$(1).o

    TESTHNF_OBJS += $(OBJDIR)/$(1).o
endef
$(foreach b,$(basename $(TESTHNF_CPPS) $(TESTHNF_CS)),$(eval $(call $(b))))

clean:
    rm -f $(TESTHNF_OBJS)

Поскольку все это довольно сложно, а преимущества довольно малы, вероятно, лучше придерживаться более простогоконструкции, которые легче понять и поддерживать:

OBJDIR       := objects
TESTHNF_CPPS := testhnf.cpp timings.cpp LongModular.cpp VeryLong.cpp VeryLongModular.cpp squfof.cpp
TESTHNF_CS   := mt19937int.c lip.c
BASENAMES    := $(basename $(TESTHNF_CPPS) $(TESTHNF_CS))
TESTHNF_OBJS := $(addprefix $(OBJDIR)/,$(addsuffix .o,$(BASENAMES)))

$(BASENAMES): %: $(OBJDIR)/%.o

clean:
    rm -f $(TESTHNF_OBJS)

Правило статическое правило .

...