Створіть змінну у файлі make, прочитавши вміст іншого файлу


82

Як я можу створити змінну на льоту з makefile, значення якої складатиме весь вміст іншого файлу даних.

Відповіді:


49

Я припускаю, що вам подобається встановлювати змінну у вашому файлі Makefile вмістом іншого файлу:

FILE=test.txt
VARIABLE=`cat $(FILE)`

target:
    echo $(VARIABLE)

3
Насправді, я не можу поставити визначення VARIABLE перш за все: оскільки PATH_TO_MY_DATA_FILE не існує, поки деякі команди не будуть запущені в цілі all:. Як альтернативу, що я зробив, це те, що я розділив речі на два make-файли (створив під-марку) і оголосив ЗМІННУ у верхній частині під-марки, і тепер це працює як шарм.
Срінатх

26
Це неправильна відповідь. Значення VARIABLE- це рядок cat $(FILE)(у лапках), який лише розширюється в рецепті оболонкою. Спробуйте роздрукувати значення цього типу $(info ${VARIABLE}).
Максим Єгорушкін

4
@MaximEgorushkin Це не неправильно. Ви просто повинні розглядати VARIABLEяк обіцянку. Це єдина версія, яка працює зі старими версіями make. Обидва :=і $(shell ...)є розширеннями GNU.
закінчується

7
Проголосовано проти. Це буде виконуватися catкожного разу, коли правило виконується. Зазвичай цього не передбачається і слід застерігати, оскільки це повільно. Крім того, якщо файл є конвеєром, він має ненавмисні побічні ефекти. Присвоєння повинно бути з :=таким чином, щоб правило не обчислювалось при заміні змінної, а при визначенні змінної. Значення заміни має бути $(shell cat $(FILE))таким, щоб catкоманда виконувалась на місці за допомогою make, а не пізніше за правилами рецепта.
Крістіан Худжер,

2
@antred, make є частиною стандартного набору інструментів UNIX / POSIX, який також включає cat. Якщо ви встановлюєте, то нормально встановлювати всі інші основні інструменти, і є дуже рідкісні обставини, коли це може спричинити труднощі. Довіра, catа не складні альтернативні правила, зробить ваші файли make-файлів набагато простішими для розуміння та майже такими ж портативними, а іноді і більш портативними.
Майкл

82

Припускаючи, що GNU робить:

file := whatever.txt
variable := $(shell cat ${file})

4
@ceving Використовуйте стандартну марку GNU. Solaris make - це не портативний додаток.
Максим Єгорушкін

8
Марка Gnu не є ні стандартною, ні більш портативною, ніж solaris. "Популярний" - це ваше слово. Якщо ми серйозно розглядаємо портативність та стандартну конформацію, дотримуйтесь posix.
把 友情 留 在 无 盐

3
У цьому випадку я б погодився з "Популярним" - не-GNU Make занадто примітивний. Якщо ви прагнете продовжувати підтримувати операційні системи 1990-х, тоді відповідь @ bb-generation, мабуть, саме те, що вам потрібно (хоча в багатьох випадках це призведе до проблем). У всіх інших випадках GNU Make є легкодоступним, або, що, швидше за все, типовим, тому, будь ласка, використовуйте його.
Guss

1
GNU make працює в будь-якому місці, так що так, він набагато портативніший, ніж будь-який інший виробник. "стандарт" може бути суб'єктивним, задоволеним.
MarcH

27

GNU make версії 4.2 підтримує операцію зчитування файлів, тож щодо чудової відповіді Максима Єгорушкіна є необов’язковий спосіб вирішити цю проблему зараз:

FILE     := test.txt
variable :=$(file < $(FILE))

Виправлена ​​помилка. Назви змінних чутливі до регістру. Назви "foo", "FOO" та "Foo" стосуються різних змінних. ( gnu.org/software/make/manual/html_node/Using-Variables.html )
Ярослав Нікітенко

лапки також не потрібні, $ (файл <"$ (FILE)") намагається відкрити "test.txt".
cagney

16

catне існує в Windows. Рішення, яке працює для Linux та Windows:

cat := $(if $(filter $(OS),Windows_NT),type,cat)
variable := $(shell $(cat) filename)

Пояснення: Здається, в Windows завжди є OSзмінна середовища, визначена рівною 'Windows_NT'. Таким чином, для Windows typeвикористовується команда, для інших catне використовується.


9

З моменту $(file op filename)додавання набагато простіше :

VARIABLE = $(file < my_file.txt)

Сторінка керівництва тут: https://www.gnu.org/software/make/manual/html_node/File-Function.html#index-file_002c-reading-from


1
Це працювало для мене за GNU Make 4.2.1, на відміну від інших запропонованих рішень :)
TabeaKischka

3
Це було представлено в GNU Make 4, і macOS все ще поставляється з
версією

4

Якщо ви використовуєте GNU make, іншим способом отримати цей ефект є використання make "include" іншого make-файлу:

З Makefile:

include "./MyFile.mak"

Створіть файл "MyFile.mak" із вмістом:

FILE := "my file content"
FILE += "more content 1"
FILE += "more content 2"

це, здається, не працює, я розуміюMakefile:1: "./MyFile.mak": No such file or directory
knocte

це, мабуть, означає, що ви використовуєте не GNU версію make .... або дійсно стару версію GNU make ... спробуйте: "make -v"
Білл Мур,

використовуючи make in mac, не впевнений, що в комплекті чи встановлений homebrew, make -vдаєGNU Make 3.81
knocte

Ви переконуєтесь, що випадково не перетворили символи TAB на пробіл у Makefile? Make у цьому відношенні майже дратує, як python.
Білл Мур

Я змусив це працювати на моєму Mac, видаливши цитати, наприклад: include ./MyFile
Чарлі Тран

3

Оскільки платформа не була вказана, ось як вона працює на Solaris:

VERSION:sh = cat VERSION

all:
        echo $(VERSION)

0

Ось більш портативне рішення, яке працює з MAKEверсією 3, де fileдиректива недоступна. Недоліком є ​​те, що для цього потрібно створити тимчасовий файл.

$(shell echo define my_variable > file.tmp)
$(shell cat my_file.txt >> file.tmp)
$(shell echo endef >> file.tmp)
include file.tmp

Основна ідея полягає у використанні defineдирективи, яка спеціально розроблена для оголошення багаторядкових змінних. Звичайно, ви можете уникнути використання shellі тимчасового файлу, якщо зможете явно написати вміст файлу для використання Makefile.

Майте на увазі, що якщо ваш файл містить $ознаки, MAKEнамагатиметься розширити їх як змінні / директиви при my_variableрозгортанні (або при призначенні, якщо ви його визначите за допомогою :=). Якщо ви хочете цього уникнути, вам потрібно уникнути їх, перш ніж включати вміст файлу. Наприклад, замість цього catви можете зробити це:

$(shell sed 's/\$$/$$$$/g' my_file.txt >> file.tmp)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.