Як я можу створити змінну на льоту з makefile, значення якої складатиме весь вміст іншого файлу даних.
Відповіді:
Я припускаю, що вам подобається встановлювати змінну у вашому файлі Makefile вмістом іншого файлу:
FILE=test.txt
VARIABLE=`cat $(FILE)`
target:
echo $(VARIABLE)
VARIABLE
- це рядок cat $(FILE)
(у лапках), який лише розширюється в рецепті оболонкою. Спробуйте роздрукувати значення цього типу $(info ${VARIABLE})
.
VARIABLE
як обіцянку. Це єдина версія, яка працює зі старими версіями make
. Обидва :=
і $(shell ...)
є розширеннями GNU.
cat
кожного разу, коли правило виконується. Зазвичай цього не передбачається і слід застерігати, оскільки це повільно. Крім того, якщо файл є конвеєром, він має ненавмисні побічні ефекти. Присвоєння повинно бути з :=
таким чином, щоб правило не обчислювалось при заміні змінної, а при визначенні змінної. Значення заміни має бути $(shell cat $(FILE))
таким, щоб cat
команда виконувалась на місці за допомогою make, а не пізніше за правилами рецепта.
cat
а не складні альтернативні правила, зробить ваші файли make-файлів набагато простішими для розуміння та майже такими ж портативними, а іноді і більш портативними.
Припускаючи, що GNU робить:
file := whatever.txt
variable := $(shell cat ${file})
GNU make версії 4.2 підтримує операцію зчитування файлів, тож щодо чудової відповіді Максима Єгорушкіна є необов’язковий спосіб вирішити цю проблему зараз:
FILE := test.txt
variable :=$(file < $(FILE))
cat
не існує в Windows. Рішення, яке працює для Linux та Windows:
cat := $(if $(filter $(OS),Windows_NT),type,cat)
variable := $(shell $(cat) filename)
Пояснення: Здається, в Windows завжди є OS
змінна середовища, визначена рівною 'Windows_NT'. Таким чином, для Windows type
використовується команда, для інших cat
не використовується.
З моменту $(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
Якщо ви використовуєте 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
make -v
даєGNU Make 3.81
include ./MyFile
Оскільки платформа не була вказана, ось як вона працює на Solaris:
VERSION:sh = cat VERSION
all:
echo $(VERSION)
Ось більш портативне рішення, яке працює з 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)