Make: извлечь целевой путь, следующий за известным - PullRequest
2 голосов
/ 13 марта 2019

Я пытаюсь оптимизировать наши цели сборки. В нашем текущем процессе у нас есть отдельные цели для 32-битной и 64-битной сборки. Из-за отдельных целей у нас есть сотни целей в нашем процессе сборки. Где мы пытаемся сделать его глобальным, то есть одной целью для 32-битной и 64-битной сборки. Я пытаюсь добиться этого с помощью кода ниже.

Целевой / выходной каталог для 32-битной сборки должен выглядеть следующим образом:

/test/scratch/<client_name>/Linux/... 

Целевой / выходной каталог для 64-битной сборки должен выглядеть следующим образом:

/test/scratch/<client_name>/Linux-64bit/... 

Таким образом, основываясь на вышеуказанных путях к целевому каталогу, я ищу строку Linux с использованием функции $(findstring) и продолжаю выполнение 32-битной команды. В противном случае он запускает 64-битную команду, как показано ниже.

RELEASE_FILES := $(TARGET_DIR)/build/test/csimtime.c
$(RELEASE_FILES): $(TGTDIRFILES)/%: %
ifneq (Linux,$(findstring $(OS),$@))
    $(test_lib_32)
else
    $(test_lib_64)
endif

$(TARGET_DIR) переменная передается в качестве параметра для создания команды

make TARGET_DIR=$(TGT32) all32

Для 64-битных мы передадим TARGET_DIR=$(TGT64).

Примечание: test_lib_32 / 64 выше - определение макроса в другом файле make, который мы включаем в текущий файл make.

Работает нормально, как и ожидалось, но я не уверен, что это лучший способ? И здесь я замечаю одну проблему: обычно переменная TGT32 / TGT64, которую мы передаем, имеет значения:

/test/scratch/<client_name>/Linux/ (for 32bit)

или

/test/scratch/<client_name>/Linux-64bit/... (for 64bit)

Если кто-то создаст клиента со строкой client_name 'Linux', он не будет работать. Он всегда будет идти в блок if и пытаться запустить 32-битную команду, даже когда мы запускаем 64-битную сборку. Как я могу справиться с этим?

Я ищу строку после 'client_name' в указанном выше пути. Не могли бы вы помочь?

Ответы [ 2 ]

0 голосов
/ 13 марта 2019

Если имя вашей целевой директории всегда что-то вроде:

/test/scratch/<client_name>/Linux/...

и в <client-name> нет символа / и пробелов, вы можете основывать свой тест на точной позиции Linux (или Linux-64bit) на пути:

TYPE := $(word 4,$(subst /, ,$(TARGET_DIR)))

ifeq ($(TYPE),Linux)
<something>
else ifeq ($(TYPE),Linux-64bit)
<something-else>
else
$(error Unknown type: $(TYPE))
endif

РЕДАКТИРОВАТЬ если позиция не постоянна, но вы знаете, что такое <client-name>, а в <client-name> нет символа / и пробелов, вы можете извлечь имя каталога, который следует <client-name> в $(TARGET_DIR) как это:

TAIL := $(subst /, ,$(TARGET_DIR))
$(foreach w,$(TAIL),$(eval TAIL := $(wordlist 2,$(words $(TAIL)),$(TAIL)))$(if $(patsubst $(CLIENT_NAME),,$(w)),,$(eval TYPE := $(word 1,$(TAIL)))))

all:
    @printf 'TYPE = $(TYPE)\n'

Демо-версия:

$ make TARGET_DIR=/a/b/test-client/Linux/c/d CLIENT_NAME=test-client
TYPE = Linux
$ make TARGET_DIR=/a/b/c/d/test-client/Linux-64bit/e/f/g CLIENT_NAME=test-client
TYPE = Linux-64bit

Пояснение:

  • TAIL := $(subst /, ,$(TARGET_DIR)) заменяет / символов в $(TARGET_DIR) на один пробел, так что он становится списком слов (по одному на каталог в пути) и присваивает результат переменной TAIL.
  • $(foreach w,$(TAIL),...) оценивает ... с переменной w, установленной последовательно для каждого слова $(TAIL).
  • $(eval TAIL := $(wordlist 2,$(words $(TAIL)),$(TAIL))) переназначает переменную TAIL, удаляя начальное слово.
  • $(if $(patsubst $(CLIENT_NAME),,$(w)),,...) оценивает ..., если $(w) равно $(CLIENT_NAME).
  • $(eval TYPE := $(word 1,$(TAIL))) назначает первое слово $(TAIL) переменной TYPE.

Могут быть более простые способы сделать то же самое ...

0 голосов
/ 13 марта 2019

Если я правильно понимаю ваш вопрос, у вас возникнут проблемы со следующим значением $(TARGET_DIR):

 /.../Linux/.../Linux-64bit

Проблема в том, что вы тестируете значение $@:

 /.../Linux/.../Linux-64bit/some/other/file

Как вы можете видеть, это делает невозможным определение того, какой Linux в пути следует использовать для решения.

Я бы предложил вместо этого попробовать:

# if $(TARGET_DIR) ends with /Linux -> 32-bit build
$(RELEASE_FILES): $(TGTDIRFILES)/%: %
ifneq ($(filter %/Linux,$(TARGET_DIR)),)
        $(test_lib_32)
else
        $(test_lib_64)
endif
...