Визначте змінну Makefile, використовуючи змінну ENV або значення за замовчуванням


78

Я намагаюся зробити просту річ:

TMPDIR ?= /tmp

test:
    @echo $(TMPDIR)

Це працює, якщо я запустив:

$ make test
/tmp

Це також працює, якщо я запустив:

$ make test -e TMPDIR=~/tmp
/home/user/tmp

Що я можу зробити, щоб це також працювало:

$ TMPDIR=~/tmp make test
/home/user/tmp

4
Е-м-м-м ... те, що у вас, ПРАЦЮЄ (якщо ви використовуєте ?=і у вас встановлено змінну середовища, тоді замість цього буде використано значення змінної середовища). У чому саме проблема (чому, на вашу думку, це не працює)?
MadScientist

1
Також просто FYI, додавання лапок до значень змінних всередині make-файлу, як правило, не є гарною ідеєю.
MadScientist,

Так, я двічі перевірив і працюю, TMPDIR ?= "/tmp"і echo $(TMPDIR)єдине, що не забути дужки навколо імені змінної.
Натім,

1
Ви використовуєте -eназад. -eкаже, щоб дозволити env vars замінювати змінні, визначені у файлі make, вони не впливають на призначення змінних, що надходить з аргументів командного рядка.
Etan Reisner,

1
До жаль Natim, але ?= робить роботу. Якщо це робить не те, що ви хочете, тоді або ваше пояснення вище заплутане, і ми не розуміємо, чого ви хочете, або щось у вашому реальному оточенні не відображається у вашому запитанні вище.
MadScientist

Відповіді:


132

Щоб продовжити мої коментарі вище, ось приклад:

T ?= foo
all:
        : '$(T)'

Тепер, якщо я запускаю Makefile різними способами, він поводиться так, як ми очікуємо (я отримую fooлише в тому випадку, якщо я не встановив Tні в командному рядку, ні в середовищі):

$ make
: 'foo'

$ make T=bar
: 'bar'

$ T=bar make
: 'bar'

Що це all:;::?
Xiphias

3
all:створює правило для цільової всіх . Крапка з комою закінчує список передумов і починає перший рядок рецептів. Останній :- рецепт; двокрапка - це спеціальний оператор оболонки POSIX, що означає, в основному, "нічого не робити". Отже, це визначає повне правило для allцілі, яка має рецепт, який нічого не робить.
MadScientist

Я насправді віддаю перевагу оригінальному формату, оскільки він працює без необхідності перетворювати пробіли у вкладки (важко поставити твердий TAB у приклад в SO). Але, мабуть, інші люди схвалили редагування так ...
MadScientist

37

Змінні, вказані в командному рядку make, перевизначають значення, призначені у файлі make :

TMPDIR := "/tmp"
test:
    @echo $(TMPDIR)

І потім:

make TMPDIR=whatever
whatever

Як правило, погана практика, коли файли make-файлів залежать від змінних середовища, ось чому передача змінних у командний рядок make є кращою.


Інший спосіб - використовувати orфункцію make :

X := $(or ${X},${X},abc)

all :
    @echo ${X}

make
abc

X=def make 
def

Насправді, вам слід просто дотримуватися використання ?=завдання.


1
Добре, це добре знати, але як я можу використовувати змінну середовища як значення за замовчуванням, якщо встановлено?
Натім,

У цьому конкретному випадку TMPDIR - це змінна, яка може існувати, і яку я хочу використовувати, якщо вона існує.
Натім,

Я намагався, TMPDIR := $(or $$TMPDIR,$$TMPDIR,"/tmp")але, здається, це не працює.
Natim

@Natim Чому ви ставите зайві знаки долара?
Максим Єгорушкін

1
Здається, що цих $(orвикликів більше, ніж потрібно. Це не працює? $(or $X,abc) ?
Нед Батчелдер,

4

Ось просте рішення:

SHELL  := env TMPDIR=$(TMPDIR) $(SHELL)
TMPDIR ?= "/tmp"

all:
  @echo $(TMPDIR)

який працює для обох сценаріїв: TMPDIR=new/path makeі make TMPDIR=new/path.


0

Одне, що ви могли зробити, це:

TMPDIR := "/tmp"

ifdef $$TMPDIR
TMPDIR := $$TMPDIR
endif

test:
    echo $(TMPDIR)

Це не працює як TMPDIR=~/tmp make, лише коли працює як make TMPDIR=~/tmp , але питання полягало в тому, щоб зробити це для обох.
kenorb
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.