Як я можу створити змінну на льоту з 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)