Принудительно заставить команды выполнять команды в одной среде

У меня есть make-файл для компиляции кроссплатформенного приложения. Для Windows я решил использовать MSVC. Для настройки цепочки инструментов компилятора (переменные среды для легкого доступа к компилятору для конкретной целевой архитектуры) MSVC предоставляет пакетный файл с именем vcvarsall, Если я вызываю его вручную, он работает нормально, и make-файл может выполняться тоже. Я попытался немного автоматизировать его, вызвав его из make-файла, но, похоже, make запускает его в другой среде, поэтому он не может найти компилятор.

Есть ли способ заставить make не выполнять некоторые команды в другой среде?

1 ответ

Решение

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

targetA: prequisitesA...
    command1        # New shell; inherits environment of `make`
    command2        # Another new shell; inherits environment of `make`
    ...

targetB: prequisitesB...
    command1 && command2    # New shell; inherits environment of `make`
    command3        # Another new shell; inherits environment of `make`
    ...

targetC: prequisitesC...
    command1 && \
    command2    # New shell; inherits environment of `make`
    command3; \
    command4    # Another new shell; inherits environment of `make`
    ...

Чтобы использовать в команде в make-recipe любые параметры среды, которые применяются при запуске vcvarsall тогда либо make должен быть запущен после vcvarsall в той же среде или унаследованной, которая сохраняет эти настройки, или же это должно быть верно для каждой команды рецепта, которая зависит от этих настроек.

Вы можете указать Make запускать все команды каждого рецепта в одной оболочке для каждого рецепта, написав псевдо-цель .ONESHELL: в make-файле. Но вряд ли это будет решением для вас.

Вероятно, подходящая автоматизация для вашего случая - написать скрипт-обертку, который вызывает vcvarsall до make,

В зависимости от структуры вашего make-файла и вашего допуска к рекурсивному make, вы можете представить себе рекурсивное решение в духе:

ARCH ?= amd64

.PHONY: all

all:
    vcvarsall $(ARCH) && $(MAKE) prog

где:-

  • ARCH (архитектура) по умолчанию amd64 если не определено на make командная строка или в вызывающей среде

  • all ваша цель по умолчанию фальшивая цель

  • prog ваша настоящая цель.

Другие вопросы по тегам