Переменное разыменование в make-файлах - PullRequest
1 голос
/ 21 марта 2011

Учитывая список путей, я хочу отделить часть каталога и часть имени файла каждого элемента списка внутри make-файла.Что-то вроде следующего

MYLIST = \
        /home/folder1/folder2/fileName1 \
        /home/folder3/folder4/fileName2 \
        /home/folder5/folder6/fileName3 \
MYLIST:
    @for elems in $(MYLIST); \
    do \
        echo $(dir $$elems); \
        echo $(notdir $$elems); \
    done

Но есть проблема с разыменованием переменной.Я получаю вывод как

 ./
 home/folder1/folder2/fileName1
 ./
 home/folder3/folder4/fileName2
 ./
 home/folder5/folder6/fileName3

, тогда как я хочу, чтобы он был

         /home/folder1/folder2/
         fileName1
         /home/folder3/folder4/
         fileName2
         /home/folder5/folder6/
         fileName3

Почему-то $ (@ D) и $ (@ F) не даютвсе части dir и fileName - только первые в списке.Может кто-нибудь сказать, пожалуйста, как об этой проблеме?

Ответы [ 3 ]

4 голосов
/ 21 марта 2011

Это происходит потому, что вы смешиваете две стадии расширения. Перед вызовом оболочки для выполнения правила все переменные make и функции раскрываются. Таким образом, $$elems становится $elems, и эта строка затем используется в качестве ввода для функций $(dir ...) и $(notdir ...). Эта строка не содержит /, поэтому dir возвращает ./, а notdir возвращает $elems. В конце в оболочке выполняется следующая команда.

@for elems in /home/folder1/folder2/fileName1 /home/folder3/folder4/fileName2 /home/folder5/folder6/fileName3; \
do \
    echo ./; \
    echo $elems; \
done

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

MYLIST = \
        /home/folder1/folder2/fileName1 \
        /home/folder3/folder4/fileName2 \
        /home/folder5/folder6/fileName3 \

MYDIRS = $(dir $(MYLIST))
MYFILES = $(notdir $(MYLIST))

MYLIST:
        @for elems in $(MYDIRS) $(MYFILES); \
        do \
            echo $$elems; \
        done


$(@D) и $(@F) не дают вам все части dir и fileName, потому что они дают файл и директорию цели текущего вызова правила. В каждый момент есть только одна цель. Вы можете использовать эти автоматические переменные, однако, чтобы делать то, что вы хотите, позволяя make выполнять цикл вместо оболочки, как показано ниже:

MYLIST = \
        /home/folder1/folder2/fileName1 \
        /home/folder3/folder4/fileName2 \
        /home/folder5/folder6/fileName3 \

all: $(MYLIST)
$(MYLIST):
    @echo $(@D)
    @echo $(@F)
1 голос
/ 21 марта 2011

Я бы предложил использовать оболочку вместо make:


MYLIST = \
        /home/folder1/folder2/fileName1 \
        /home/folder3/folder4/fileName2 \
        /home/folder5/folder6/fileName3
MYLIST:
    for elems in $(MYLIST); \
    do \
    echo $$(dirname $$elems); \
    echo $$(basename $$elems); \
    done

Конечно, на этом этапе эхо избыточно, и вы также можете сделать:

for elems in $(MYLIST); \
    do \
    dirname $$elems; \
    basename $$elems; \
    done
0 голосов
/ 25 марта 2011

Я нашел другой способ сделать это сейчас ...

MYLIST = \
    /home/folder1/folder2/fileName1 \
    /home/folder3/folder4/fileName2 \
    /home/folder5/folder6/fileName3

MYLIST:
    @$(foreach ELEMS,$(MYLIST), echo $(dir $(ELEMS)); echo $(notdir $(ELEMS));)

Не знаю, как я пропустил это раньше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...