Строка-инструкция make-файла для получения значений переменных


Оглавление (нажмите, чтобы открыть):

Продвинутое использование qmake

Многие файлы проекта qmake просто описывают исходные и заголовочные файлы, относящиеся к проекту, используя список определений имя = значение и имя += значение. qmake также предоставляет дополнительные операторы, функции и области видимости, которые можно использовать для обработки информации, переданной в объявлениях переменных. Эти продвинутые средства позволяют генерировать из одного файла проекта Make-файлы для разнообразных платформ.

Операторы

Во многих файлах проекта операторы присваивания (=) и дополнения (+=) могут быть использованы для добавления всей информации о проекте. Типичный шаблон использования — присвоить переменной список значений и добавить дополнительные значения в зависимости от результата разнообразных тестов. Так как qmake определяет некоторые переменные, используя значения по умолчанию, иногда необходимо использовать оператор удаления (-=) чтобы отфильтровать ненужные значения. Следующие операторы могут быть использованы для манипуляции содержимым переменных.

Оператор = присваивает переменной значение:

В строке выше переменную TARGET устанавливают равной myapp. Это затрет все значения, ранее установленные для TARGET кроме myapp.

Оператор += добавляет новое значение к списку значений переменной:

В строке выше QT_DLL добавляется в конец списка определений препроцессора, помещаемый в генерируемый Make-файл.

Оператор -= удаляет значение из списка значений переменной:

В строке выше QT_DLL удаляется из списка определений препроцессора, помещаемого в генерируемый Make-файл.

Оператор *= добавляет значение в список значений переменной, но только если его там не было. Это предотвращает многократное добавление значений в переменную. Например:

В строке выше значение QT_DLL будет добавлено в список определений препроцессора только если этого значения там еще не было. Обратите внимание на то, что функция unique() также можно использовать для того, чтобы убедиться что переменные содержат только один экземпляр каждого значения.

= заменяет все значения, которые соответствуют регулярному выражению, на указанное значение:

В строке выше все значения списка, которые начинаются на QT_D или QT_T, заменяются на QT.

Оператор $$ используется для извлечения содержимого переменной и может быть использован для передачи значений между переменными или передачи их в функции:

Области видимости

Области видимости аналогичны операторам if в процедурных языках программирования. Если некоторое условие истинно, то объявления внутри области видимости обрабатываются.

Области видимости и условия

Области видимости записываются как условие с рядом объявлений, содержащихся внутри пары скобок; например:

Вышеприведенный код добавит файл paintwidget_win.cpp к источникам, перечисленным в сгенерированном Make-файле, если qmake используется на платформе Windows. Если qmake используется не на платформе Windows, определение будет пропущено.

Используемые в данной области видимости условия могут быть также инвертированы для предоставления альтернативного набора объявлений, который будет обработан только если начальное условие ложно. Например, предположим, мы хотим обработать что-либо на всех платформах за исключением Windows. Мы можем добиться этого инвертированием области видимости, например так:

Области видимости могут быть вложенными для объединения более чем одного условия. Например, если вы хотите включить отдельный файл для определенной платформы только если разрешена отладка, тогда напишите следующее:

Чтобы избежать написания множества вложенных областей видимости вы можете вложить их используя оператор :. Вложенные области видимости в примере выше можно переписать следующим образом:

Вы также можете использовать оператор : для выполнения отдельной строки условных присваиваний; например:

В строке выше QT_DLL добавляется к переменной DEFINES только на платформе Windows. Как правило, оператор : ведет себя как логический оператор AND, объединяя вместе несколько условий, и требует истинности их всех.

Вы также можете предоставить альтернативные объявления внутри области видимости используя область видимости else. Каждая область видимости else обрабатывается если условия для предшествующих областей видимости были ложными. Это позволяет вам писать сложные тесты, комбинируя с другими областями видимости (разделенные оператором : как показано выше). Например:

Конфигурация и области видимости

Значения, сохраненные в переменной CONFIG, специально обрабатываются для qmake. Каждое из возможных значений может быть использовано в качестве условия для области видимости. Например, список значений, содержащихся в CONFIG, может быть расширен значением opengl:

В результате этой операции все области видимости, которые проверяют на opengl, будут обработаны. Мы можем использовать эту возможность чтобы дать финальному исполняемому файлу соответствующее имя:

Эта возможность облегчает изменение конфигурации проекта без потери всех пользовательских настроек, которые могут понадобиться для определенной конфигурации. В вышеприведенном коде обрабатываются объявления в первой области видимости, а финальный исполняемый файл будет называться application-gl. Однако, если opengl не указано, взамен будут обрабатываться объявления во второй области видимости, а финальный исполняемый файл будет называться application.

Так как можно поместить ваши собственные значения в строку CONFIG, это предоставляет вам удобный способ для настройки файлов проекта и тонкой настройки генерируемых Make-файлов.

Значения области видимости платформы

В добавление к значениям win32, macx и unix, используемым во многих условиях области видимости, с помощью областей видимости можно проверять различные другие встроенные значения, зависящие от платформы и компилятора. Они базируются на спецификациях платформ, предоставленных в каталоге Qt mkspecs. Например, следующие строки из файла проекта показывают текущую используемую спецификацию и проверяют на спецификацию linux-g++:

Вы можете проверить на все остальные комбинации платформа-компилятор, если спецификация имеется в каталоге mkspecs.

Переменные

Многие переменные, используемые в файлах проекта, являются специальными переменными, которые использует qmake при генерации Make-файлов, например, DEFINES, SOURCES и HEADERS. Вы можете создавать переменные для своих нужд; qmake создает новые переменные с заданным именем когда встретит присваивание этому имени. Например:

Не имеется ограничений на то, что вы можете делать со своими переменными, поскольку qmake будет их игнорировать пока при обработке области видимости не понадобится их вычислить.

Вы также можете присвоить значение текущей переменной, к имени которой добавлен префикс $$, переменной с другим именем. Например:

Теперь переменная MY_DEFINES содержит то, что есть в переменной DEFINES на этот момент в файле проекта. Это эквивалентно:

Второе представление позволяет вам добавлять содержимое переменной к другому значению без их разделения пробелом. Например, следующим обеспечивается то, что у финального исполняемого файла будет заданное имя, которое включает используемый шаблон проекта:

Переменные можно использовать для сохранения содержимого переменных окружения. Их можно вычислять во время запуска qmake или включить в сгенерированный Make-файл для вычисления при сборке проекта.

Для получения содержимого значения окружения при запуске qmake используйте оператор $$(. ):

В вышеприведенном присваивании значение переменной окружения PWD читается при обработке файла проекта.

Для получения содержимого значения окружения в тот момент, когда обрабатывается сгенерированный Make-файл, используйте оператор $(. ):

В вышеприведенном присваивании, значение PWD читается непосредственно при обработке файла проекта, но $(PWD) присваивается DESTDIR в сгенерированном Make-файле. Это делает процесс сборки более гибким до тех, пока переменная окружения корректно установлена при обработке Make-файла.

Специальный оператор $$[. ] может быть использован для получения доступа к различным опциям конфигурирования, которые были установлены при сборке Qt:

Доступность переменных с помощью этого оператора обычно используется для разрешения интеграции с Qt сторонних подключаемых модулей и компонентов. Например, подключаемый модуль Qt Designer можно установить рядом со встроенными подключаемыми модулями Qt Designer‘а, если в его файле проекта сделано следующее объявление:

Функции обработки переменной

qmake предоставляет набор встроенных функций для обработки содержимого переменных. Эти функции обрабатывают переданные им аргументы и возвращают в качестве результата значение или список значений. Для того чтобы присвоить переменной результат, необходимо использовать оператор $$ с этим типом функции таким же образом, как присваивается содержимое одной переменной другой:

Этот тип функции должен использоваться с правой стороны присваиваний (т.е., в качестве операнда).

Можно определить ваши собственные функции для обработки содержимого переменных. Такие функции можно определить следующим образом:

В следующем примере функция получает имя переменной как единственный аргумент, извлекает список значений из переменной с помощью встроенной функции eval() и составляет список файлов:

Условные функции

qmake предоставляет встроенные функции, которые можно использовать в качестве условий при написании областей видимости. Эти функции не возвращают значения, но вместо этого служат признаком «успеха» или «неудачи»:

Этот тип функции используется только в условных выражениях.

Вы можете определить собственные функции для предоставления условий для областей видимости. В следующем примере проверяется, существует ли каждый файл в списке и возвращается true если все они существуют, или false — если нет:

Добавление новых функций конфигурации

qmake позволяет вам создавать собственные функции, которые можно включать в файлы проекта, добавив их имена в список значений, задаваемых переменной CONFIG. Функции — это коллекции пользовательских функций и определений в файлах .prf, которые могут постоянно находиться в одном из стандартных каталогов. Размещение этих каталогов описывается в нескольких местах, а qmake при поиске файлов .prf проверяет каждое из них в следующем порядке:

  1. В каталоге, включенном в переменную окружения QMAKEFEATURES; содержит список каталогов, разделенных двоеточием.
  2. В каталоге, включенном в переменную свойства QMAKEFEATURES; содержит список каталогов, разделенных двоеточием.
  3. В каталоге функций, находящемся внутри каталога mkspecs. Каталоги mkspecs могут располагаться внизу всех каталогов, включенных в переменную окружения QMAKEPATH (список каталогов, разделенных двоеточием). ($QMAKEPATH/mkspecs/ )
  4. В каталоге функций, находящемся внизу каталога, предоставляемого переменной окружения QMAKESPEC. ($QMAKESPEC/ )
  5. В каталоге функций, находящемся в каталоге data_install/mkspecs. (data_install/mkspecs/ )
  6. В каталоге функций, который существует на том же уровне, что каталог указанный в переменной окружения QMAKESPEC. ($QMAKESPEC/../ )

В следующих каталогах функций производится поиск файлов функций:

  1. features/unix, features/win32 или features/macx, в зависимости от используемой платформы
  2. features/

Например, рассмотрим следующее присваивание в файле проекта:

С этим добавлением к переменной CONFIG, qmake будет искать файл myfeatures.prf в местах, перечисленных выше после завершения разбора вашего файла проекта. На Unix системах будет разыскиваться следующий файл:

  1. $QMAKEFEATURES/myfeatures.prf (для каждого каталога, перечисленного в переменной окружения QMAKEFEATURES)
  2. $$QMAKEFEATURES/myfeatures.prf (для каждого каталога, перечисленного в переменной окружения QMAKEFEATURES)
  3. myfeatures.prf (в корневом каталоге проекта)
  4. $QMAKEPATH/mkspecs/features/unix/myfeatures.prf и $QMAKEPATH/mkspecs/features/myfeatures.prf (для каждого каталога, перечисленного в переменной окружения QMAKEPATH)
  5. $QMAKESPEC/features/unix/myfeatures.prf и $QMAKESPEC/features/myfeatures.prf
  6. data_install/mkspecs/features/unix/myfeatures.prf и data_install/mkspecs/features/myfeatures.prf
  7. $QMAKESPEC/../features/unix/myfeatures.prf и $QMAKESPEC/../features/myfeatures.prf

Замечание: Имена файлов .prf должны быть в нижнем регистре.

Как распечатать переменную в make файле


В моем make файле у меня есть переменная ‘NDK_PROJECT_PATH’, мой вопрос в том, как я могу ее распечатать при компиляции?

Кто-нибудь знает, почему он не работает для меня?

Вы можете распечатать переменные при чтении make файла (при условии, что GNU make, поскольку вы правильно пометили этот вопрос), используя этот метод (с переменной с именем «var»):

Вы можете добавить эту конструкцию в любой рецепт, чтобы увидеть, что make перейдет в оболочку:

Теперь происходит то, что make хранит весь рецепт ( $(info $$var is [$])echo Hello world ) в виде одной рекурсивно раскрытой переменной. Когда make решает запустить рецепт (например, когда вы говорите ему построить all ), он расширяет переменную и затем передает каждую результирующую строку отдельно в оболочку.

Итак, в болезненных деталях:

  • Он расширяет $(info $$var is [$])echo Hello world
  • Для этого он сначала расширяет $(info $$var is [$])
    • $$ становится буквальным $
    • $ становится 🙂 (скажем)
    • Побочным эффектом является то, что $var is [:-)] появляется на стандартном
    • Расширение $(info. ) хотя и пустое
  • Сделать осталось с echo Hello world
    • Сделайте отпечатки echo Hello world на stdout, чтобы вы знали, что именно попросит оболочка
  • Оболочка печатает Hello world на стандартный вывод.

Добавьте в свой файл Makefile следующее правило:

Затем, если вы хотите узнать значение переменной makefile, просто:

Как указано в приведенном выше ответе «bobbogo» и согласно руководству GNU Make, вы можете использовать info/warning/error для отображения текста.

Чтобы напечатать переменные,

когда вы используете ‘error’, выполнение make останавливается после отображения строки ошибки

Если вам просто нужен какой-то вывод, вы хотите использовать $(info) самостоятельно. Вы можете сделать это в любом месте Makefile, и он покажет, когда эта строка будет оценена:

Будет выводить VAR=» » всякий раз, когда обрабатывает эту строку. Это поведение очень зависит от положения, поэтому вы должны убедиться, что расширение $(info) происходит ПОСЛЕ того, что все, что может изменить $(VAR) , уже произошло!

Более общий вариант заключается в создании специального правила для печати значения переменной. Вообще говоря, правила выполняются после назначения переменных, поэтому это покажет вам значение, которое фактически используется. (Хотя для правила можно изменить ). Хорошее форматирование поможет уточнить, к какой переменной задано, и функция $(flavor) сообщит вам какая переменная что-то есть. Итак, в этом правиле:

  • $* расширяется до того, что шаблон % соответствует правилу.
  • $($*) расширяется до значения переменной, имя которой задается $* .
  • [ и ] четко обозначают расширение переменной. Вы также можете использовать » и » или аналогичные.
  • $(flavor $*) сообщает вам, какая именно переменная. ПРИМЕЧАНИЕ: $(flavor) принимает имя переменной, а не ее расширение. Итак, если вы скажете make print-LDFLAGS , вы получите $(flavor LDFLAGS) , это то, что вы хотите.
  • $(info text) обеспечивает вывод. Произведите отпечатки text на его stdout как побочный эффект расширения. Расширение $(info) хотя и пусто. Вы можете думать об этом как @echo , но важно, чтобы он не использовал оболочку, поэтому вам не нужно беспокоиться о правилах цитирования оболочки.
  • @true существует только для того, чтобы предоставить команду для правила. Без этого, make также выводит print-blah is up to date . Я чувствую, что @true делает более понятным, что это означает, что это не-op.

Admins SU

Знакомство с CMake. Часть 2. Переменные, условия, сообщения, опции. 0

В прошлой статье я рассмотрел основные задачи, решаемые системой сборки CMake, а также простенький проект. Сейчас я постараюсь внести ясность в механику работы этой системы сборки, чтобы было понятно, как CMake работает с CMakeLists.txt файлами. Это позволит с первого раза безошибочно создавать сложные кроссплатформенные проекты и легко читать чужие проекты.

Порядок чтения

Файл CMakeLists.txt читается только в одном случае – когда выполняется непосредственно сам cmake. Все сообщения, ошибки и предупреждения, возникающие в процессе чтения файла, выводятся только этой командой.

CMakeLists.txt читается построчно, и, как правило, одна строка выполняет одну команду. Допускаются пустые строки и комментарии, начинающиеся с символа #, причем комментарий не обязательно должен начинаться с начала строки.

Также часть файла может не быть прочитана по какому-либо условию.

Переменные

CMake работает в основном с переменными. Они задаются явно, записываются в результате выполнения команд, или используются как аргументы для команд. Переменная – это просто какое-нибудь имя и соответствующее ему значение. Внутри каждая переменная представляет собой просто строковое значение, и интерпретируется в зависимости от команды. Чтобы подставить значение переменной, используется конструкция $, а для обращения к переменной (изменения) используется просто её имя. Переменные объявлять не надо, они создаются сами в момент первого обращения.

Надо понимать, что подстановка значения переменной через конструкцию $<> работает как простая текстовая замена.

Национальная библиотека им. Н. Э. Баумана
Bauman National Library

Персональные инструменты

Makefile

MAKEFILE

Интернет-тип носителя text/x-makefile
Тип формата Автоматизация сборки
Стандарт POSIX

Makefile – файл, содержащий набор инструкций для программы make. Программа make с помощью этого файла позволяет автоматизировать процесс компиляции программы и выполнять при этом различные действия. При запуске make по умолчанию ищет файл Makefile в текущей папке и обрабатывает его (можно изменить это поведение, чтобы открывался другой файл с набором инструкций, если ввести команду make -f другое_имя_makefile ).

Содержание

Обзор

Чаще всего, Makefile показывает как компилировать и компоновать программу. Используя C / C ++ в качестве примера, когда исходный файл C / C ++ изменяется, он должен быть перекомпилирован. Если файл заголовка был изменен, каждый исходный файл C / C ++, содержащий заголовочный файл, должен быть перекомпилирован для обеспечения безопасности. Каждая компиляция создает объектный файл, соответствующий исходному файлу. Наконец, если какой-либо исходный файл был перекомпилирован, все объектные файлы, будь то новые или сохраненные из предыдущих компиляций, должны быть связаны друг с другом для создания новой исполняемой программы. [Источник 1] Эти инструкции с их зависимостями указаны в make- файле, Если ни один из файлов, которые являются предварительными условиями, не был изменен с момента компиляции программы, никаких действий не происходит. Для крупных программных проектов использование Make-файлов может существенно сократить время сборки, если изменилось только несколько исходных файлов.

Структура файла

Комментарии, как это принято в UNIX скриптах, начинаются с символа # и продолжаются до конца строки.
Обычно в файле содержатся метки, идентифицирующие «цели» (targets, см. далее). Метка начинается с начала строки и оканчивается двоеточием :. После двоеточия могут идти так называемые зависимости, dependencies (сразу непонятно, что это такое и для чего надо, но дальше по ходу дела станет яснее). Обычно это имена файлов, либо ссылки на цели.
Если в качестве dependencies указана последовательность целей, то они будут выполняться друг за другом.
Если в качестве dependencies указаны имена файлов (обычно объектных), то утилита make может проверить — нужно их компилировать, или нет (мне непонятно, как она проверяет, однако это работает). Например, если компилируется несколько исходных файлов в несколько объектных, то некоторые исходные файлы не требуется каждый раз перекомпилировать заново, если они не изменялись. Для больших проектов это важно, поскольку существенно экономит время сборки программы (в нашем случае — получение двоичной прошивки для AVR).
Для упрощения содержимого Makefile и для удобства используются переменные.

Пример задания переменной (здесь в переменную записана командная строка вызова программатора):

После задания переменной на неё можно ссылаться так:

  • После задания в одной строке цели (цель: [зависимость1] .. [зависимостьN]) в последующих строках могут задаваться так называемые правила (rules). Каждое правило должно ОБЯЗАТЕЛЬНО начинаться с символа табуляции (таким способом make отслеживает правила и другие цели). Правило — это просто обычная команда (вызов компилятора, копирование, удаление и проч.), выполняемая шеллом.
  • Переменные $@ , $ , $^ называются автоматическими (automatic variables).

$@ заменяется на текущую цель.
$ которая заменяется на первую зависимость из списка.
$^ которая заменяется на список всех зависимостей с их каталогами.

Итак, при работе с проектом может потребоваться автоматизировать следующие часто повторяющиеся действия:
1. Компиляция программы (вводимая команда будет выглядеть как make hex).
2. Запись двоичного файла (make flash).
3. Запись бит «перемычек» (make fuse, для микроконтроллеров AVR это обычно 2 байта).
4. Полная запись микроконтроллера (и памяти и перемычек), выполняются действия и 2, и 3.
5. Очистка проекта — удаление всех промежуточных файлов, образующихся при компиляции, обычно объектных (make clean).
6. Стирание микроконтроллера (очистка flash и сброс перемычек в исходное состояние).
7. Бэкап проекта (make backup), будет выполняться цель 5 (clean), а затем архивирование файлов.
8. Вывод подсказки по возможным вариантам работы с проектом (просто make, при этом выводится подсказка по make hex, make flash, make fuse, make clean).

Для каждого такого действия 1..8 в Makefile прописывается блок команд, этот блок идентифицируется целью (target). Имя цели по сути является меткой, по которой переходит управление при обработке команды, переданной программе make. Для действия 1 это будет запуск компилятора (цель hex), для 2 — вызов программатора (цель flash) и т. д.

Рассмотрим для примера ветку обработки цели hex (команда make hex) по шагам:

  • Пользователь вводит команду make hex.
  • Программа make открывает файл Makefile, ищет цель hex и начинает её обработку.
  • Для цели hex указана зависимость main.hex и ни одного правила (строка 131). Программа make ищет цель main.hex и начинает её обработку.
  • Для цели main.hex указана зависимость main.elf (строка 175) и несколько правил. Программа make ищет цель main.elf и начинает её обработку (правила цели main.hex будут отрабатываться после окончания обработки цели main.elf).
  • Для цели main.elf указаны зависимости usbdrv и $(OBJECTS) (строка 172), а также одно правило (вызов компилятора для получения файла main.elf). Программа make ищет цель usbdrv и начинает её обработку.
  • Для цели usbdrv не указано зависимостей (строка 169), только одно правило (копирование папки usbdrv в текущий каталог). Выполняется это правило, цель usbdrv завершена и происходит возврат к обработке цели main.elf.
  • Зависимости, входящие в переменную $(OBJECTS) (строка 172), не являются целями, это просто имена файлов, которые должны быть получены при компиляции. Поэтому сразу начинается выполняться правило, запускающее компилятор (строка 173). В результате те объектные файлы, которые должны быть скомпилированы, появляются в соответствующих каталогах, и появляется выходной файл main.elf (двоичный файл, который может использоваться в качестве входного для эмулятора или симулятора при отладке программы). Цель main.elf завершена, происходит возврат к обработке цели main.hex (строка 175).
  • Начинается обработка правил цели main.hex. Команда rm удаляет старые файлы прошивок flash и eeprom, avr-objcopy генерирует новую прошивку main.hex из файла main.elf, avr-size просто отображает информацию о размере секций в файле main.hex. Обработка цели main.hex закончена, происходит возврат к обработке цели hex.
  • Все зависимости цели hex обработаны, правил у цели hex нет. Работа make на этом завершается.

Проблемы и их решения

1. Makefile в среде Windows (Makefile работает при помощи пакета MSYS) завершается с ошибкой на команде xcopy, например (выполнение команды make backup):

Проблема решается добавлением в начало Makefile строки «SHELL=cmd.exe». Вот пример рабочего Makefile, в котором эта ошибка устранена:

2. Сетевые (UNC) пути необходимо заключать в двойные кавычки, иначе они будут неправильно переданы интерпретатору cmd.exe. Вот так:

3. Отлаживать makefile удобно с помощью команды echo, выводя в консоль значения переменных. Пример:

Операционная система

Система make родилась в мире UNIX и постепенно переползла и на Windows вместе с портами GNU-компиляторов (gcc). Если открыть пример готового Makefile, то он поначалу может показаться полной абракадаброй, поскольку содержимое файла подчиняется заранее заданному набору правил, которые необходимо предварительно изучить. Для простоты рассмотрим пример работы с проектом AVR и компилятором gcc.

Unix-подобный

Makefiles происходит от Unix-подобных систем и по-прежнему является основным механизмом создания программного обеспечения в таких средах.

Microsoft Windows

Windows поддерживает изменение make-файлов с помощью утилиты nmake . Стандартные Unix, такие как make-файлы, могут быть выполнены в Windows в среде Cygwin.

Содержание

Makefiles содержит пять видов вещей: явные правила , неявные правила , определения переменных , директивы и комментарии .


  • Явное правило говорит , когда и как переделать один или несколько файлов, называемых целями правила. В нем перечислены другие файлы, от которых зависят целевые объекты, называемые предпосылками цели, а также могут давать рецепт для создания или обновления целей.
  • Неявное правило говорит , когда и как переделать класс файлов на основе их имен. В нем описывается, как цель может зависеть от файла с именем, близким к целевому, и дает рецепт для создания или обновления такой цели.
  • Определение переменной — это строка, которая указывает значение текстовой строки для переменной, которая может быть заменена в тексте позже.
  • Директива является инструкцией для макияжа , чтобы сделать что — то особенное, читая Makefile , такие как чтение другого Makefile.
  • ‘#’ в строке файла makefile начинает комментарий . Он и остальная часть строки игнорируются.

Правила

Простой make-файл состоит из «правил» со следующей из форм [Источник 2] :

Зависимость или «prerequisites» (также называемая предварительным условием) — это файл, который используется как вход для создания цели. Необходимым условием является файл, который используется как вход для создания цели.

Цель(target) часто зависит от нескольких файлов.Однако правило, определяющее рецепт для цели, не обязательно имеет какие-либо предварительные условия. Например, правило, содержащее команду delete, связанную с целевым «чистым», не имеет предварительных условий.

Рецепт (recipe)- это действие , которое make выполняет. Рецепт может иметь более одной команды, либо в одной строке, либо в каждой строке. Обратите внимание: вам нужно поместить символ табуляции в начале каждой линии рецептов. Это неясность, на которой попадаются неосторожные. Если вы предпочитаете префикс своих рецептов символом, отличным от табуляции, вы можете установить RECIPEPREFIX переменную на альтернативный символ.

Затем правило объясняет, как и когда переделывать определенные файлы, которые являются объектами конкретного правила. make выполняет рецепт на предпосылках для создания или обновления цели. Правило также может объяснить, как и когда выполнять действие.

Файл makefile может содержать другой текст помимо правил, но простой makefile должен содержать только правила. Правила могут выглядеть несколько сложнее, чем показано в этом шаблоне, но все они более или менее соответствуют шаблону .

Условные части Make-файлов

Пример условного

В следующем примере условного выражения makeиспользуется один набор библиотек, если CCпеременная ‘НКУ’и другой набор библиотек в противном случае. Он работает, контролируя, какая из двух линий рецепта будет использоваться для правила. В результате получается, что ‘CC = GCC’как аргумент для makeизменений не только того, какой компилятор используется, но и какие библиотеки связаны.

В этом условном случае используются три директивы: один ifeq, один else и один endif.

ifeq Директива начинается условная, и определяет условие. Он содержит два аргумента, разделенных запятой и окруженных круглыми скобками. Подстановка переменных выполняется по обоим аргументам, а затем их сравнивают. Строки файла makefile, следующие за ними, ifeqвыполняются, если совпадают два аргумента; в противном случае они игнорируются.

else Директива вызывает следующие строки надо соблюдать , если предыдущий условный не удалось. В приведенном выше примере это означает, что вторая альтернативная команда связывания используется всякий раз, когда первая альтернатива не используется. Необязательно иметь elseусловное выражение .

endif Директива заканчивается условное. Каждое условие должно заканчиваться на endif. Далее следует текст безусловного make-файла.

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

Когда переменная CCимеет значение ‘НКУ’, приведенный выше пример имеет такой эффект:

Когда переменная CCимеет любое другое значение, эффект таков:

Эквивалентные результаты могут быть получены другим способом путем условного назначения переменной, а затем безоговорочно использовать переменную:

Синтаксис условий

Синтаксис простого условного с no else заключается в следующем:

Текста , если-правда могут быть любые строки текста, которые должны быть рассмотрены в рамках Makefile , если условие истинно. Если условие ложно, вместо этого текст не используется.

Синтаксис сложного условного выражения следующий:

При необходимости может быть столько « else условно-директивных » положений. Когда данное условие истинно, используется text-if-true, и никакое другое предложение не используется; если условие не истинно, используется text-if-false . Текста , если правда и текст-невыполненный- может быть любым количеством строк текста.

Синтаксис условной-директивы одинаковый, является ли условное просто или сложным; после elseили нет. Существует четыре разных директивы, которые проверяют разные условия. Вот их таблица:

Разверните все ссылки переменных в arg1 и arg2 и сравните их. Если они идентичны, текст-if-true эффективен; в противном случае текст-if-false , если таковой имеется, эффективен.

Часто вы хотите проверить, имеет ли переменная непустое значение. Когда значение получается из сложных разложений переменных и функций, разложения, которые вы считаете пустыми, могут фактически содержать пробельные символы и, следовательно, не считаются пустыми. Однако вы можете использовать эту stripфункцию (см. Текстовые функции ), чтобы избежать интерпретации пробела как непустого значения. Например:

будет оценивать text-if-empty, даже если расширение $(foo)содержит пробельные символы.

Разверните все ссылки переменных в arg1 и arg2 и сравните их. Если они разные, текст-if-true эффективен; в противном случае текст-if-false , если таковой имеется, эффективен.

ifdef variable-name ifdef Форма принимает имя переменной в качестве аргумента, а не ссылка на переменную. Если значение этой переменной имеет непустое значение, текст-if-true действует; в противном случае текст-if-false , если таковой имеется, эффективен. Переменные, которые никогда не были определены, имеют пустое значение. Текстовое имя переменной расширяется, поэтому это может быть переменная или функция, которая расширяется до имени переменной. Например:

Ссылка на переменную $(foo)расширяется, давая bar, что считается именем переменной. Переменная barне разворачивается, но ее значение проверяется, чтобы определить, не является ли она непустой.

Обратите внимание, что ifdefпроверяет только, имеет ли переменная значение. Он не расширяет переменную, чтобы увидеть, не является ли это значение непустым. Следовательно, тесты с использованием ifdefreturn true для всех определений, за исключением тех, которые похожи foo =. Чтобы проверить пустое значение, используйте ifeq ($(foo),). Например,

наборы ‘frobozz’to’да’, в то время как:

ifndef variable-name Если переменная variable-name имеет пустое значение, текст-if-true эффективен; в противном случае текст-if-false , если таковой имеется, эффективен. Правила расширения и тестирования имени переменной идентичны ifdefдирективе.

Дополнительные пробелы разрешены и игнорируются в начале строки условной директивы, но вкладка не допускается. (Если строка начинается с вкладки, она будет считаться частью рецепта правила). Помимо этого, дополнительные пробелы или вкладки могут быть вставлены без какого-либо эффекта, кроме как внутри имени директивы, так и внутри аргумента. Комментарий, начинающийся с ‘#’может появиться в конце строки.

Остальные две директивы, которые играют роль в условном выражении, являются else и endif. Каждая из этих директив написана как одно слово без аргументов. Дополнительные пробелы разрешены и игнорируются в начале строки, а также пробелы или вкладки в конце. Комментарий, начинающийся с ‘#’может появиться в конце строки.

Условные обозначения влияют на makeиспользуемые строки make-файла . Если условие истинно, makeчитает строки текста-if-true как часть файла makefile; если условие ложно, полностью makeигнорирует эти строки. Из этого следует, что синтаксические единицы make-файла, такие как правила, могут безопасно разделяться в начале или в конце условного.

makeоценивает условные выражения при чтении make-файла. Следовательно, вы не можете использовать автоматические переменные в тестах условных чисел, потому что они не определены до тех пор, пока не будут запущены рецепты.

Чтобы предотвратить недопустимую путаницу, не разрешается запускать условное выражение в одном файле makefile и заканчивать его другим. Однако вы можете написать include директиву в условном выражении , если вы не пытаетесь завершить условие внутри включенного файла.

Условные обозначения,которые проверяют флаги

Вы можете написать условие, которое проверяет makeфлаги команд, такие как ‘-t’, используя переменную MAKEFLAGSвместе с findstringфункцией (см. Функции для подстановки и анализа строк ). Это полезно, когда touchэтого недостаточно, чтобы обновить файл.

findstringФункция определяет , будет ли отображаться одна строка в качестве подстроки другого. Если вы хотите протестировать «-t’flag, use’T’как первая строка и значение MAKEFLAGSкак другое.

Например, вот как организовать использование ‘ranlib -t’для окончательной маркировки архивного файла:

«+» префикс отмечает эти строки рецептов как «рекурсивные», так что они будут выполнены, несмотря на использование’-t’.

Выполнение

Makefile выполняется с make командой, например make [options] [target1 target2 . ] . По умолчанию, когда make ищет make-файл, если имя файла makefile не было включено в качестве параметра, он пытается использовать следующие имена: makefile и Makefile.

Примеры

2. Использование действий по умолчанию.

По умолчанию, make начинает с первого правила (не считая правил, имена целей у которых начинаются с ‘.’). Это называется главной целью по умолчанию. В нашем случае это правило edit. Если файл edit новее чем объектные файлы, от которых он зависит, то ничего не произойдет. В противном случае, прежде чем make сможет полностью обработать это правило, он должен рекурсивно обработать правила для файлов, от которых зависит edit. Каждый из этих файлов обрабатывается в соответствии со своим собственным правилом. Перекомпеляция должна быть проведена, если исходный файл или любой из заголовочных файлов, упомянутых среди зависимостей, обновлен позднее, чем объектный файл, или если объектный файл не существует. Правилу clean не соответствует никакого создаваемого файла и, соответственно, clean ни от чего не зависит и само не входит в список зависимостей. При запуске по умолчанию clean вызываться не будет. Для его выполнения необходимо явно указать цель при запуске make: make clean .

3. Для сокращения записи можно использовать переменные и действия по умолчанию (неявные правила)

Переменная objects позволила использовать единожды написанный список объектных файлов, а для объектных файлов в make встроено неявное правило по умолчанию

4. Специальная цель .PHONY является встроенной в make и определяет свои зависимости как цели-имена, которым нет соответствия в виде файлов. Если данное правило пропустить, то создание в текущем каталоге файла с именем clean заблокирует выполнение make clean. Использование правил по умолчанию позволяет изменить стиль записей зависимостей:

Статья Переменные в CMD, команда SET и арифметика

Dragokas

Very kind Developer

Ограничение от -2147483647 до 2147483647.

Вывод значения переменных

%RANDOM% — раскрывается в случайное десятичное число между 0 и 32767.(от 0 до (2^17)-1)

Выводит случайное число от 0 до 9.
У меня это число по нелепой псевдослучайности цифру секунды
%CD% — раскрывается в строку текущей директории.
%DATE% — раскрывается в текущую дату, используя тот же формат команды DATE.
%TIME% — раскрывается в текущую дату, используя формат команды TIME.
%ERRORLEVEL% — раскрывается в текущее значение ERRORLEVEL.
Уровень ошибки, 0 — это нет ошибки, 1 — это есть ошибка, а другие это номера ошибки.

Чтобы получить полный список переменных и их значений введите команду SET

Операции со строковыми или численными переменными

Соединение 2-ух строковых переменных

Вывод определенного(ых) символа(ов) из строки
Символы номеруются начиная с 0!

Существуют 2 способа использовать переменную в переменной, например: вывод n-ого символа

Первый способ с call set

писать в do
С циклами мы разберемся в следующей статье.
Но, пока уточню: если код второго способа юзать в пакетном файле (BATнике), то вместо %i юзаем %%i.

Операции с числовыми переменными

Увеличивание на единицу


Унарные операторы
(Не знаю, как они называются)

Побитовое И (AND)

Побитовое И — это бинарная операция, действие которой эквивалентно применению логического И к каждой паре битов, которые стоят на одинаковых позициях в двоичных представлениях операндов.
Другими словами, если оба соответствующих бита операндов равны 1, результирующий двоичный разряд равен 1; если же хотя бы один бит из пары равен 0, результирующий двоичный разряд равен 0.

Побитовое ИЛИ (OR)

Побитовое ИЛИ — это бинарная операция, действие которой эквивалентно применению логического ИЛИ к каждой паре битов, которые стоят на одинаковых позициях в двоичных представлениях операндов.
Другими словами, если оба соответствующих бита операндов равны 0, двоичный разряд результата равен 0; если же хотя бы один бит из пары равен 1, двоичный разряд результата равен 1.

Побитовое исключающее ИЛИ (XOR)

Побитовое исключающее ИЛИ (или побитовое сложение по модулю два) — это бинарная операция, действие которой эквивалентно применению логического исключающего ИЛИ к каждой паре битов, которые стоят на

одинаковых позициях в двоичных представлениях операндов.
Другими словами, если соответствующие биты операндов различны, то двоичный разряд результата равен 1; если же биты совпадают, то двоичный разряд результата равен 0.

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

Двоичный арифметический сдвиг

Арифметический сдвиг аналогичен логическому, но значение слова считается знаковым числом, представленным в дополнительном коде.
Так, при правом сдвиге старший бит сохраняет свое значение. Левый арифметический сдвиг идентичен логическому.

Максимальный размер отдельной переменной среды составляет 8192 байта.(у меня выходило только 8184, наверное это вместе с названием. )
Максимальный общий размер всех переменных среды, включая имена переменных и знак равенства, составляет 65 536 Кбайт.

И я забыл, про 8-ричную и 16-ричную систему счисления в CMD

Числовые значения рассматриваются как десятичные, если перед ними не стоит префикс 0x для шестнадцатеричных чисел, и 0 для восьмеричных чисел. Например, числа 0x12, и 022 обозначают десятичное число 18.

Обратите внимание на запись восьмеричных числе: 08 и 09 не являются допустимыми числами, так как в восьмеричной системе исчисления цифры 8 и 9 не используются.

Отладка работы утилиты make

Советы и рекомендации о том, как заставить make работать на вас, а не против вас

Сборка большинства программ для UNIX® и Linux® производится путем запуска утилиты make . Эта утилита считывает файл (обычно носящий имя «makefile» или «Makefile», здесь он называется просто «makefile»), в котором содержатся инструкции, и выполняет различные действия, необходимые для сборки программы. Во многих случаях сам makefile полностью генерируется специальной программой; например, для разработки процедур сборки используются программы autoconf/automake . В иных программах может потребоваться изменение файла makefile напрямую, и, конечно же, вам придется написать такой файл при разработке новой программы.

Фраза «утилита make» является ошибочной. Существует как минимум три различных наиболее распространенных варианта этой утилиты: GNU make, System V make и Berkeley make. Каждый из них вырос из базовой спецификации времен начала становления UNIX и в каждом из них добавлены новые возможности. Это привело к сложной ситуации: некоторые наиболее часто используемые функции, например, включение в makefile других файлов по ссылке, перестали быть портируемыми! Единственным решением является написание программы, которая создает файлы makefile. Поскольку утилита GNU make бесплатна и широко распространена, некоторые разработчики просто кодируют для нее; кроме того, некоторые проекты, берущие свои корни из BSD, потребуют от вас использования Berkeley make (которая также бесплатна).

Менее распространена, но всё ещё значима утилита smake Йорга Шиллинга (Jörg Schilling), а также отсутствующий пятый член семейства, первоначальная утилита make, определяющая комплекс основных функций, общих для всех остальных утилит. Несмотря на то, что утилита smake не используется по умолчанию на всех системах, это хорошая реализация make, и она является предпочтительной в некоторых программах (особенно в написанных Шиллингом).

Давайте рассмотрим некоторые из наиболее распространенных проблем, с которыми вы можете встретиться при работе с файлами makefile.

Определение файла makefile

Для того чтобы выполнить отладку работы утилиты make, вы должны уметь читать содержимое файла makefile. Как вы уже знаете, назначением файла makefile является предоставление инструкций программе сборки. Одной из ключевых возможностей утилиты make является управление зависимостями: make пытается перестроить только то, что изменилось при обновлении программы. В общем, это выражается рядом правил зависимости. Такое правило выглядит следующим образом:

Листинг 1. Вид правила зависимости

В этой конструкции видна, вернее — не видна, основная проблема, с которой люди встречаются при написании своего первого файла. Отступ выполняется знаком табуляции. Он не содержит ни одного пробела. Сообщение об ошибке, выдаваемое Berkeley make для файла, в котором использованы пробелы, не очень информативно:

Листинг 2. Сообщение об ошибке Berkeley make

Утилита GNU make, хотя и не может обработать файл, дает более полезный совет:

Листинг 3. Сообщение об ошибке GNU make

Следует обратить внимание, что зависимости и команды необязательны; необходимо указывать лишь цель и двоеточие. Итак, мы поговорили о синтаксисе. Какова же семантика? Семантика такова, что если вы желаете провести сборку цели , будет проведена проверка всех зависимостей. Фактически, утилита будет рекурсивно пытаться собрать их; если у зависимости, в свою очередь, есть ещё одна зависимость, она будет обработана до того, как будет продолжена обработка правила. Если цель target : существует и ее дата не является более ранней, чем даты всех объектов, перечисленных в пункте зависимости , ничего не выполняется. Если target не существует или одна или несколько зависимостей обновились, утилита make выполнит команды instructions . Зависимости обрабатываются в порядке указания. Если зависимости не указаны, команды будут выполнены в безусловном порядке. Зависимости также называются источниками.

Если в командной строке указана цель (например, make foo ), то утилита make будет пытаться построить эту цель. В противном случае она будет пытаться построить первую цель, указанную в файле. Некоторые разработчики берут за правило указывать первую цель следующим образом:

Листинг 4. Наиболее часто используемое условное указание первой цели

Некоторые предполагают, что утилита make использует это правило потому, что оно называется «default» («по умолчанию»). Это не так; оно используется потому, что это первое правило в файле. Вы можете дать ему любое название, какой только пожелаете, но название «default» хорошо тем, что оно несет в себе смысловую нагрузку для читающего код. Помните о том, что создаваемый вами файл makefile будут читать не только программы make, но и люди.

Фиктивные цели

В общем случае предполагается, что функция цели заключается в создании файла из других файлов. В действительности это не всегда так. В большинстве файлов makefile есть хотя бы пара правил, которые никогда не создадут цель. Рассмотрим как пример следующее правило:

Листинг 5. Пример фиктивной цели

Это дает утилите make следующие инструкции — если она желает собрать цель all , сначала необходимо убедиться в том, что существуют актуальные версии «hello», «goodbye» и «fibonacci». Тогда. ничего не делать. Никаких команд не дается. После выполнения этого правила не создается файла с названием «all». Это фиктивная цель. В некоторых версиях утилиты make используется технический термин «фиктивная» («phony») цель.

Фиктивные цели используются для организационных нужд и являются отличным средством создания понятного и удобочитаемого файла makefile. Например, часто можно увидеть правило, похожее на это:

Листинг 6. Разумное использование фиктивной цели

Здесь указывается порядок операций процесса сборки.

Специальные цели и источники

Определен ряд специальных целей, оказывающих особое влияние на утилиту make и предоставляющих средства настройки. Точный перечень изменяется от одной реализации к другой; наиболее часто используется цель .SUFFIXES , «источником» для которой является ряд шаблонов, добавляемых к списку найденных расширений (суффиксов) файлов. Специальные цели не учитываются в обычном правиле, гласящем, что make по умолчанию строит первую цель в файле makefile.

В некоторых версиях утилита make позволяет определять специальные цели наряду с зависимостями для данной цели, например, .IGNORE, что обозначает, что ошибки команды, используемой для сборки этой цели, будут проигнорированы, как если бы перед ними стоял знак комментария. Эти флаги не всегда портируемы, но знать их для отладки файла makefile необходимо.

Общие правила

В make существуют неявные правила выполнения общих преобразований на основе расширений файлов. Например, при отсутствии файла makefile создайте файл с названием «hello.c» и выполните команду make hello :

Листинг 7. Пример неявных правил для файлов C

В файлах makefile для более крупных программ можно просто указать перечень необходимых модулей объектов (hello.o, world.o и так далее), после чего указать правило преобразования файлов .c в файлы .o:

Листинг 8. Правило преобразования файлов .c в файлы .o

На самом деле в большинстве утилит make уже есть правило, очень похожее на это; если вы затребуете у make построить файл file.o и в наличии будет соответствующий файл file.c, утилита сработает как положено. Сочетание «$ $CFLAGS заменяется на «FLAGS». Для того, чтобы указать переменную make, заключите её наименование в скобки: $(CFLAGS) . В противном случае вы получите переменную $C , за которой будет следовать текст FLAGS .

У некоторых переменных есть специальные значения, зависящие от правил, в которых они используются. Среди наиболее часто используемых:

  • $ — Источник, из которого должна быть изготовлена цель
  • $* — Базовое имя цели (без расширения и имени каталога)
  • $@ — Полное имя цели

Авторы Berkeley make выводят эти переменные из обращения, но пока они всё ещё портируемы. Во всяком случае, портируемы отчасти; точные определения в различных реализациях утилиты make могут различаться. Любая сложная программа, написанная с их помощью, скорее всего, будет ограничена конкретной реализацией.

Сценарии командного процессора

Иногда бывает желательно выполнять задачи определенного рода за пределами портируемости утилиты make. Традиционным решением является написание встроенного сценария командного процессора (shell), поскольку make выполняется именно через него. Рассмотрим, как это работает.

Во-первых, необходимо помнить, что, несмотря на то, что обычно сценарии командного процессора пишутся в несколько строк, их можно сжать в одну строку, разделяя элементы точкой с запятой. Во-вторых, нужно отдавать себе отчет в том, что это нечитаемо. Можно найти компромисс: писать сценарии с обычными отступами, но заканчивая каждую строку «; \». Такое завершение синтаксически (точкой с запятой) разделяет команды процессора, но в то же время составляет текстовую часть одной команды make, которая передается командному процессору целиком. Например, в файле makefile верхнего уровня могут содержаться следующие строки:

Листинг 9. Разрыв строк в сценарии командного процессора

Здесь показаны три вещи, которые всегда необходимо помнить. Во-первых, используйте точки с запятой и обратные слэши. Во-вторых, для создания переменных используйте $(VARIABLE) . В-третьих, используйте $$ для передачи сценарию знака доллара. Вот и всё! Это действительно просто.

Префиксы

По умолчанию утилита make выводит каждую выполняемую команду и завершает свою работу, если какая-либо из команд вернула ошибку. В некоторых случаях существует вероятность того, что команда возвращает код ошибки, но вы все равно желаете продолжить сборку. В случае, если первым символом команды является дефис (-), оставшаяся часть строки выполняется, но код результата выполнения игнорируется.

Если вы не желаете, чтобы команда выводилась на экран, начните ее со знака @. Этот вариант чаще всего используется для вывода сообщений:

Листинг 10. Подавление вывода

Без знака @ эти инструкции приведут к выводу следующей информации:

Листинг 11. Команды без знака @

Несмотря на то, что символ @ фактически не влияет на действия, выполняемые утилитой make, он остается очень популярной функцией.

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

Некоторые нужные всем действия невозможно сделать портируемыми. Однако для решения этих проблем существует несколько обходных путей.

Включение файлов

Одной из наиболее удручающих проблем совместимости долгое время является обработка включений в файлы makefile. Ранние реализации утилиты make, в отличие от современных, не всегда предоставляли пути для выполнения этой операции. Синтаксис GNU make — простая команда include file . Традиционный синтаксис Berkeley — .include «file» . На сегодняшний день по крайней мере одна реализация Berkeley также поддерживает нотацию GNU, однако это делают не все. Портируемое решение, найденное autoconf и Imake , состоит в простом включении определения каждой переменной, которая, по вашему мнению, может вам понадобиться.


Некоторые программы просто ставят условием использование GNU make. Другим необходима Berkeley make. Третьим — smake. Если вам очень нужно включать файлы, нет ничего немыслимого в том, чтобы просто указать, с помощью какой утилиты make будет строиться ваше дерево файлов. (Из трех портируемых утилит с открытым исходным кодом я предпочитаю Berkeley make.)

Получение переменных во вложенных сборках

Действительно хорошего способа реализации этой задачи не существует. Если использовать include-файл, вы сталкиваетесь с проблемой портируемости включения файла. Если определять переменные в каждом файле, будет очень сложно их исправлять. Если задать их только в файле верхнего уровня, выполнить независимую сборку в подкаталогах будет невозможно, потому что переменные не заданы!

В зависимости используемой вами версии утилиты make довольно неплохое решение состоит в том, чтобы определять переменные в каждом файле только при условии, что они еще не установлены; поэтому в случае полной сборки изменения, сделанные на верхнем уровне, будут влиять также и на подкаталоги. Конечно же, если зайти в подкаталог и выполнить утилиту make там, вы получите другие, несовместимые результаты.

Эта ситуация усугубляется отсутствием включаемых файлов, что может подтвердить каждый, кто хотя бы раз сталкивавшийся с файлами makefile утилиты Imake на несколько тысяч строк.

Некоторые авторы пропагандируют более простое решение: вообще не использовать утилиту make рекурсивно. Для большинства проектов это подходящее решение, которое может значительно упростить (и ускорить!) компиляцию. Вероятно, каноническим источником можно считать статью Питера Миллера (Peter Miller), «Рекурсивное использование Make вредно» (см. Ссылки).

Что делать в случае возникновения проблем

Во-первых, не нужно паниковать. До написания окончательной версии разработчики сталкиваются с множеством непонятных проблем, связанных с утилитой make. Неявные правила, неожиданные замещения переменных и синтаксические ошибки встроенных сценариев командного процессора — это только начало развлечений.

Прочтите сообщение об ошибке. Действительно ли оно выдано make — или чем-то, что вызывает make? Если вы используете вложенную сборку, вам придется пробираться через дебри сообщений об ошибках, чтобы найти фактическую ошибку.

Если не удалось найти программу, проверьте, установлена ли она. Если это так, проверьте пути; у некоторых разработчиков есть привычка указывать в файлах makefile абсолютные пути, что может привести к возникновению ошибок на других системах. Если вы производите установку в папку /opt, а в makefile указаны ссылки на /usr/local/bin, сборка завершится ошибкой. Исправьте путь.

Проверьте ваши часы; более того, посмотрите на даты создания файлов в дереве сборки и сравните их с датами создания других файлов вашей системы и вашими часами. Поведение утилиты make при подаче на вход хронологически противоречивых данных может варьировать от безобидного до сюрреалистического. Если у вас есть проблемы с часами (например, у некоторых «новых» файлов установлена дата создания в 1970 году), вам придется исправить их. Вам поможет утилита «touch». Сообщения, которые вы получаете при разнице во времени, бывают весьма неочевидными.

Если сообщение об ошибке уведомляет вас о синтаксической ошибке или о том, что не установлено или установлено неправильно множество переменных, попробуйте использовать другую версию make. Например, некоторые программы выдают загадочные ошибки при работе с gmake, но прекрасно собираются с помощью smake. Совсем таинственные ошибки могут означать, что вы используете с GNU make файл makefile, подготовленный для Berkeley, или наоборот. Программы, изначально написанные для Linux, часто предполагают наличие GNU make и выдают ошибку в самых неожиданных местах, если встречают что-либо иное, даже если в документации об этом не сказано ни слова.

В этом случае будут крайне полезны отладочные флаги. Используя в GNU make флаг -d , вы получите ОГРОМНЫЙ объем информации, в том числе полезной. В Berkeley make флаг -d имеет несколько дополнительных флагов; -d A представляет полное множество, можно использовать отдельные подмножества; например, -d vx выдаст отладочную информацию о назначении переменных ( v ), при этом все команды будут выполняться с ключом sh -x , чтобы командный процессор выводил все команды точно так, как он их получает. Отладочный флаг -n приводит к выводу утилитой make перечня действий, которые она считает необходимым выполнить; он не всегда верен, но часто наводит на мысли о том, где именно кроется ошибка.

Вашей целью в отладке файла makefile является поиск того, что пытается собрать утилита make, и какие команды, по её мнению, будут использованы для сборки. Если утилита make выбирает правильные команды, но они не выполняются, возможно, дело не в отладке make — а может, и в ней. Например, если попытка компиляции программы завершилась ошибкой, связанной с наличием нечитаемых символов, это может означать, что что-то прошло не так на более ранних этапах сборки! Если вы не можете понять, что же не так с командой, и похоже, что всё должно работать, существует большая вероятность того, что один из файлов ранее был собран утилитой make с ошибкой.

Документация

Как часто бывает, основная документация к GNU make, к сожалению, не доступна в формате man; вместо этого вам придется использовать систему info, и у вас не получится просто набрать man make и посмотреть интересующую вас информацию. Как бы то ни было, документация достаточно полна.

Крайне сложно получить хорошую документацию по «безопасному набору» функций, которые поддерживаются во всех реализациях. Документация к Berkeley make и GNU make обычно описывает добавленные расширения, однако перед тем как полагаться на какие бы то ни было конкретные утверждения, бывает полезно их проверить.

Развивающееся со временем расхождение между версиями BSD привело к возникновению едва уловимых отличий в реализации утилиты make. Из трех этих версий наиболее активно поддерживается на других системах утилита make из NetBSD; система NetBSD pkgsrc используется на других платформах и существенно опирается на реализацию make NetBSD.

21.2. Сборочная утилита make

21.2. Сборочная утилита make

Если вы уже собирали прикладную программу из исходных кодов, то обратили внимание на стандартную последовательность команд: make; make install .

Без утилиты make не обходится создание ни одного серьезного проекта. Эта утилита управляет сборкой большого проекта, состоящего из десятков и сотен файлов. Программа make может работать не только с компилятором gcc, но и с любым компилятором для любого языка программирования, способным запускаться из командной строки.

Директивы утилиты make служат для определения зависимостей между файлами проекта и находятся в файле по имени Makefile, расположенном в каталоге сборки.

Разберемся, как пишутся make-файлы. Общий формат make-файла выглядит так:

Цель — это метка для некоторой последовательности команд (например, install) или результирующий файл, который нужно «построить» — скомпилировать или скомпоновать.

Цели должны отделяться друг от друга хотя бы одной пустой строкой. Список необходимых файлов — это перечень файлов или других целей, которые нужны для достижения данной цели; он может быть и пустым.

Последовательность команд — это команды, которые нужно выполнить для достижения цели. Последовательность команд должна отделяться от начала строки символом табуляции, иначе вы получите ошибку «missing separator» (нет разделителя).

Make-файл может содержать комментарии — они начинаются символом #.

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

MODFLAGS:= -O3 -Wall -DLINUX -I$(PATH)

$(CC) $(MODFLAGS) -c proga.c

Чтобы обратиться к макроопределению в команде или в другом макроопределении, нужно использовать конструкцию $(имя). Макроопределение может включать в себя другое, ранее определенное, макроопределение.

Формат запуска утилиты make:

make [-f файл] [ключи] [цель]

Ключ -f указывает файл инструкций, который нужно использовать вместо Makefile. Если этот ключ не указан, то make ищет в текущем каталоге файл Makefile и начинает собирать указанную цель. Если цель не указана, то выполняется первая встреченная в make-файле. Сборка выполняется рекурсивно: make сначала выполняет все цели, от которых зависит текущая цель. Если зависимость представляет собой файл, то make сравнивает его время последней модификации со временем целевого файла: если целевой файл старше или отсутствует, то будет выполнена указанная последовательность команд. Если целевой файл моложе, то текущая цель считается достигнутой.

Если нужно избежать пересборки какого-то из файлов проекта, то можно искусственно «омолодить» его командой touch, которая присвоит ему в качестве времени последней модификации текущее время. Если нужно, наоборот, принудительно пересобрать цель, то следует «омолодить» один из файлов, от которых она зависит.

Работа программы make заканчивается, когда достигнута цель, указанная в командной строке. Обычно это цель all, собирающая все результирующие файлы проекта. Другими распространенными целями являются install (установить собранную программу) и clean (удалить ненужные файлы, созданные в процессе сборки).

В листинге 21.2 представлен make-файл, собирающий небольшой проект из двух программ client и server, каждая из которых компилируется из одного файла исходного кода.

Листинг 21.2. Примерный make-файл

all: client server

$(CC) client.с -о client

$(CC) server.с -о server

Обычно при вызове утилиты make не нужно задавать никаких ключей. Но иногда использование ключей бывает очень кстати (таблица 21.1).

Ключи команды make Таблица 21.1

Создание файлов с заданным текстом с переменной взятой из файла

Здравствуйте! Задача такая. Есть два файла list.txt и speed.txt со списками.
Необходимо взять первую строку из первого файла, создать файл с этим именем и записать в него текст вида:
A=100
B=X
C=50
, где X — это переменная из файла speed.txt в первой строке.
И повторить это с остальными строками.

Как по отдельности сделать разобрался, но вместе скомпоновать не могу.

12.10.2020, 16:08

BAT-ник для создания файла с заданным текстом и вставка в него имен файлов и их расширения из списка
Добрый день В общем стоит такая задача: В некую папку C:\PATH периодически закидываются файлы.

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

Создание текстового файла с заданным текстом внутри
Итак, в шарпе я 1 из 30, и вот из этого я прошу вас разъяснить мне как наложить функцию на кнопку.

Циклическое создание файлов с текстом
Доброго времени суток всем! Есть задача создать 100 файлов с расширением *.cfg и текстом внутри.

Создание txt файла с текстом, полученным из названия файла в папке
Здравствуйте! В папке содержится огромное число файлов (более 300 тыс в каждой папке), которые.

12.10.2020, 16:47 2

именно три строки именно с такими значениями и только во второй строке значение меняется — писать в каждый новый файл, да?

именно переменная?
покажите содержимое «speed.txt»

так в первой строке все-таки или

12.10.2020, 17:15 [ТС] 3

Вот например как созать файлы из списка:
For /F «delims=» %%A in (list.txt) do (
echo>%%A
)
Записать текст в файл:
echo Текст >%%A

Да. Кол-во строк дописать не трудно.

100Mbit/s
50Mbit/s
75Mbit/s
20Mbit/s
60Mbit/s

12.10.2020, 17:39 4

из файла list.txt — тут понятно

но когда создали файл с именем из второй строки из list.txt в этот файл пишем все также первую строку speed.txt или тоже берем данные из второй строки

переменная из первой строки
почему вы так называете, я вижу просто значения, переменная это, например: %SystemRoot%
а так тогда правильно говорить — данные (информация, значение) из первой строки, это все очень важно.

Добавлено через 2 минуты
приведите пример лучше.

12.10.2020, 17:39
12.10.2020, 17:44 5
12.10.2020, 17:47 [ТС] 6

Из файла speed.txt берём уже вторую.
Из list третью из speed третью.

Потому что в каждом новом созданном файле %%s будет разной. Поэтому я и назвал переменной.
Ну или можно так сказать: в переменную %%s будут подставляться данные/значение из файла speed.txt
%%s — это Х если не понятно.

Добавлено через 46 секунд

12.10.2020, 23:43 7

Решение

Windows Batch file
13.10.2020, 09:33 [ТС] 8
16.10.2020, 16:24 [ТС] 9

А как добавить сюда третий файл со значениями, который надо подставить?
В этих местах понятно:

16.10.2020, 21:03 10
16.10.2020, 21:08 [ТС] 11
16.10.2020, 21:29 12

Fiance,
не, в такие игры я не играю — составлять кучу файлов, считывать из них информацию опять же как, везде первую строку или по-отношению к первому файлу или результату уже вторую или никакую

давайте вы подумаете, составите ОДИН файл, содержащий необходимую информацию, например:
ваши
A=100
B=X
C=50
и
100Mbit/s
50Mbit/s
75Mbit/s
20Mbit/s
60Mbit/s

примерно
aaa=100=100Mbit/s
bbb=80=75Mbit/s
ccc=24=45Mbit/s
dd2=f4=2Mbit/s

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

Сборка программы с помощью GNU Make

make предназначена для отслеживания зависимостей одних файлов от других, выявления «устаревших» файлов при помощи сравнения времен модификации файлов и выполнения команд для «обновления» устаревших файлов. Позволяет автоматизировать процессы трансляции, компоновки, запуска модульных тестов и развертывания системы за счет описания соответствующих сценариев на специальном языке

Сценарии Make описываются в т.н. файле проекта. Проектом называется совокупность файлов, зависящих друг от друга. Файл описания проекта перечисляет зависимости между файлами и задает команды для обновления зависимых файлов. Имя файла описания проекта задается опцией –f командной строки программы make и по умолчанию предполагается равным Makefile или makefile. Если имя файла проекта явно не задано, при запуске утилита ищет в текущем каталоге файл с указанными выше именами, и, если такой файл существует, выполняет команды из него.

по описанию проекта в файле Makefile или makefile программа make определяет, какие файлы устарели и нуждаются в обновлении и запускает соответствующие команды.

Обычно программы на языках Си или Си++ представляют собой совокупность нескольких .c (.cpp) файлов с реализациями функций и .h файлов с прототипами функций и определениями типов данных. Как правило, каждому .c файлу соответствует .h файл с тем же именем.

Предположим, что разрабатываемая программа называется earth и состоит из файлов arthur.c, arthur.h, trillian.c, trillian.h, prosser.c, prosser.h.

Разработка программы ведется в POSIX-среде с использованием компилятора GCC.

Простейший способ скомпилировать программу — указать все исходные .c файлы в командной строке gcc:

Компилятор gcc выполнит все этапы компиляции исходных файлов программы и компоновку исполняемого файла earth. Обратите внимание, что в командной строке gcc указываются только .c файлы и никогда не указываются .h файлы.

Компиляция и компоновка при помощи перечисления всех исходных файлов в аргументах командной строки GCC допустима лишь для совсем простых программ. С ростом числа исходных файлов ситуация очень быстро становится неуправляемой. Кроме того, каждый раз все исходные файлы будут компилироваться от начала до конца, что в случае больших проектов занимает много времени. Поэтому обычно компиляция программы выолняется в два этапа: компиляция объектных файлов и компоновка исполняемой программы из объектных файлов. Каждому .c файлу теперь соответствует объектный файл, имя которого в POSIX-системах имеет суффикс .o. Таким образом, в рассматриваемом случае программа earth компонуется из объектных файлов arthur.o, trillian.o и prosser.o следующей командой:

Каждый объектный файл должен быть получен из соответствующего исходного файла следующей командой:

Обратите внимание, что явно задавать имя выходного файла необязательно. Оно будет получено из имени компилируемого файла заменой суффикса .c на суффикс .o. Итак, для компиляции программы earth теперь необходимо выполнить четыре команды:

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

  • если изменение внесено в один файл, например, в файл prosser.c, нет необходимости перекомпилировать файлы trillian.o или arthur.o; достаточно перекомпилировать файл prosser.o, а затем выполнить компоновку программы earth;
  • компиляция объектных файлов arthur.o, trillian.o и prosser.o не зависит друг от друга, поэтому может выполняться параллельно на многопроцессорном (многоядерном) компьютере.

В случае нескольких исходных .c и .h файлов и соответствующих промежуточных .o файлов отслеживать, какой файл нуждается в перекомпиляции, становится сложно, и здесь на помощь приходит программа make. По описанию файлов и команд для компиляции программа makе определяет, какие файлы нуждаются в перекомпиляции, и может выполнять перекомпиляцию независимых файлов параллельно.

Файл A зависит от файла B, если для получения файла A необходимо выполнить некоторую команду над файлом B. Можно сказать, что в программе существует зависимость файла A от файла B. В нашем случае файл arthur.o зависит от файла arthur.c, а файл earth зависит от файлов arthur.o, trillian.o и prosser.o. Можно сказать, что файл earth транзитивно зависит от файла arthur.c. Зависимость файла A от файла B называется удовлетворенной, если:

  • все зависимости файла B от других файлов удовлетворены;
  • файл A существует в файловой системе;
  • файл A имеет дату последней модификации не раньше даты последней модификации файла B.

Если все зависимости файла A удовлетворены, то файл A не нуждается в перекомпиляции. В противном случае сначала удовлетворяются все зависимости файла B, а затем выполняется команда перекомпиляции файла A.

Например, если программа earth компилируется в первый раз, то в файловой системе не существует ни файла earth, ни объектных файлов arthur.o, trillian.o, prosser.o. Это значит, что зависимости файла earth от объектных файлов, а также зависимости объектных файлов от .c файлов не удовлетворены, то есть все они должны быть перекомпилированы. В результате в файловой системе появятся файлы arthur.o, trillian.o, prosser.o, даты последней модификации которых будут больше дат последней модификации соответствующих .c файлов (в предположении, что часы на компьютере идут правильно, и что в файловой системе нет файлов «из будущего»). Затем будет создан файл earth, дата последней модификации которого будет больше даты последней модификации объектных файлов.

В получившейся конфигурации все зависимости всех файлов друг от друга удовлетворены, и поэтому для компиляции программы earth не нужно выполнять никаких команд

Предположим теперь, что в процессе разработки был изменен файл prosser.c. Его время последнего изменения теперь больше времени последнего изменения файла prosser.o. Зависимость prosser.o от prosser.c становится неудовлетворенной, и, как следствие, зависимость earth от prosser.o также становится неудовлетворенной. Чтобы удовлетворить зависимости необходимо перекомпилировать файл prosser.o, а затем файл earth. Файлы arthur.o и trillian.o можно не трогать, так как зависимости этих файлов от соответствующих .c файлов удовлетворены. Такова общая идея работы программы make и, на самом деле, всех программ управления сборкой проекта: ant https://ant.apache.org/, scons https://www.scons.org/ и др

Хотя утилита make присутствует во всех системах программирования, вид управляющего файла или набор опций командной строки могут сильно различаться. Далее будет рассматриваться командный язык и опции командной строки программы GNU make. В дистрибутивах операционной системы Linux программа называется make. В BSD, как правило, программа GNU make доступна под именем gmake.

Файл описания проекта может содержать описания переменных, описания зависимостей и описания команд, которые используются для компиляции. Каждый элемент файла описания проекта должен, как правило, располагаться на отдельной строке. Для размещения элемента описания проекта на нескольких строках используется символ продолжения \ точно так же, как в директивах препроцессора языка Си.

Определения переменных записываются следующим образом:

Использование переменной записывается в одной из двух форм:

$( ) или $ < >— Эти формы равнозначны.

Переменные рассматриваются как макросы, то есть использование переменной означает подстановку текста из определения переменной в точку использования. Если при определении переменной были использованы другие переменные, подстановка их значений происходит при использовании переменной (опять так же, как и в препроцессоре языка Си)

Зависимости между компонентами определяются следующим образом:

Где — имя цели, которое может быть либо именем файла, либо некоторым именем, обозначающим действие, которому не соответствует никакой файл, например clean. Список целей в правой части задает цели, от которых зависит .

Если описание проекта содержит циклическую зависимость, то есть, например, файл A зависит от файла B, а файл B зависит от файла A, такое описание проекта является ошибочным.

Команды для перекомпиляции цели записываются после описания зависимости. Каждая команда должна начинаться с символа табуляции (\t). Если ни одной команды для перекомпиляции цели не задано, будут использоваться стандартные правила, если таковые имеются. Для определения, каким стандартным правилом необходимо воспользоваться, обычно используются суффиксы имен файлов. Если ни одна команда для перекомпиляции цели не задана и стандартное правило не найдено, программа make завершается с ошибкой.

Для программы earth простейший пример файла Makefile для компиляции проекта может иметь вид:

Однако, в этом описании зависимостей не учтены .h файлы. Например, если файл arthur.h подключается в файлах arthur.c и trillian.c, то изменение файла arthur.h должно приводить к перекомпиляции как arthur.c, так и trillian.c. Получается, что .o файлы зависят не только от .c файлов, но и от .h файлов, которые включаются данными .c файлами непосредственно или косвенно. С учетом этого файл Makefile может приобрести следующий вид:

Первой в списке зависимостей обычно записывается «главная» зависимость, а затем записываются все остальные файлы-зависимости.

В командной строке программы make можно задать имя цели, которую требуется (при необходимости) перекомпилировать. Так, при запуске

будет при необходимости перекомпилирован только файл prosser.o и те файлы, от которых он зависит, все прочие файлы затронуты не будут. Если в командной строке имя цели не указано, берется первая цель в файле. В нашем случае это будет цель earth.

Если придерживаться хорошего стиля написания Makefile, то каждый Makefile должен содержать как минимум два правила: all – основное правило, которое соответствует основному предназначению файла, и правило clean, которое предназначено для удаления всех рабочих файлов, создаваемых в процессе компиляции. В случае программы earth рабочими файлами можно считать сам исполняемый файл программы earth, а также все объектные файлы.

С учетом этих дополнений файл Makefile примет вид:

Обратите внимание, что у правила clean отсутствует список файлов, от которых этот файл зависит. Поскольку существование файла с именем clean в рабочем каталоге не предполагается, команда rm -f . будет выполняться каждый раз, когда make запускается на выполнение командой

Данный файл, безусловно, решает задачу автоматизации сборки программы earth. Теперь можно придать этому файлу более общий вид, чтобы в этот файл легче было вносить изменения.

Во-первых, можно параметризовать название используемого компилятора, а также предоставить возможность управлять параметрами командной строки компилятора. Для задания компилятора можно определить переменную CC, для задания опций командной командной строки компиляции объектных файлов — переменную CFLAGS, а для задания опций командной строки компоновки выходной программы — переменную LDFLAGS.

Получим следующий файл:

Теперь можно изменить используемый компилятор, не только отредактировав Makefile, но и из командной строки. Например, запуск программы make в виде

-позволит для компиляции программы использовать не gcc, а Intel компилятор Си. Аналогично запуск

-позволит включить отладочную информацию в генерируемые объектные файлы и исполняемую программу

Во-вторых, можно избавиться от дублирования имен файлов сначала в зависимостях, а потом в выполняемых командах. Для этого могут быть использованы специальные переменные $^, $ include deps.make

Для генерации файла deps.make с зависимостями воспользуемся опцией -MM компилятора gcc:

Файл deps.make зависит от всех .c и .h файлов, из которых собирается программа. Может показаться, что это правило не будет работать, так как в Makefile необходимо включить файл deps.make, для генерации которого необходимо выполнить Makefile, то есть возникает циклическая зависимость, однако GNU make умеет корректно обрабатывать такие ситуации.

Для того, чтобы не выписывать списки .c и .h файлов несколько раз, в начале Makefile можно определить переменные:

Более того, список объектных файлов можно получать из списка .c файлов заменой суффикса .c на .o:


В итоге получили следующий Makefile:

Этот файл можно легко модифицировать для сборки других проектов с помощью изменения значений переменных CFILES, HFILES и TARGET.

Пример файла C++ проекта:

Для просмотра результирующих значений переменных полезно просматривать вывод команды: make -p

Продвинутое использование qmake

Многие файлы проекта qmake просто описывают исходные и заголовочные файлы, относящиеся к проекту, используя список определений имя = значение и имя += значение. qmake также предоставляет дополнительные операторы, функции и области видимости, которые можно использовать для обработки информации, переданной в объявлениях переменных. Эти продвинутые средства позволяют генерировать из одного файла проекта Make-файлы для разнообразных платформ.

Операторы

Во многих файлах проекта операторы присваивания (=) и дополнения (+=) могут быть использованы для добавления всей информации о проекте. Типичный шаблон использования — присвоить переменной список значений и добавить дополнительные значения в зависимости от результата разнообразных тестов. Так как qmake определяет некоторые переменные, используя значения по умолчанию, иногда необходимо использовать оператор удаления (-=) чтобы отфильтровать ненужные значения. Следующие операторы могут быть использованы для манипуляции содержимым переменных.

Оператор = присваивает переменной значение:

В строке выше переменную TARGET устанавливают равной myapp. Это затрет все значения, ранее установленные для TARGET кроме myapp.

Оператор += добавляет новое значение к списку значений переменной:

В строке выше QT_DLL добавляется в конец списка определений препроцессора, помещаемый в генерируемый Make-файл.

Оператор -= удаляет значение из списка значений переменной:

В строке выше QT_DLL удаляется из списка определений препроцессора, помещаемого в генерируемый Make-файл.

Оператор *= добавляет значение в список значений переменной, но только если его там не было. Это предотвращает многократное добавление значений в переменную. Например:

В строке выше значение QT_DLL будет добавлено в список определений препроцессора только если этого значения там еще не было. Обратите внимание на то, что функция unique() также можно использовать для того, чтобы убедиться что переменные содержат только один экземпляр каждого значения.

= заменяет все значения, которые соответствуют регулярному выражению, на указанное значение:

В строке выше все значения списка, которые начинаются на QT_D или QT_T, заменяются на QT.

Оператор $$ используется для извлечения содержимого переменной и может быть использован для передачи значений между переменными или передачи их в функции:

Области видимости

Области видимости аналогичны операторам if в процедурных языках программирования. Если некоторое условие истинно, то объявления внутри области видимости обрабатываются.

Области видимости и условия

Области видимости записываются как условие с рядом объявлений, содержащихся внутри пары скобок; например:

Вышеприведенный код добавит файл paintwidget_win.cpp к источникам, перечисленным в сгенерированном Make-файле, если qmake используется на платформе Windows. Если qmake используется не на платформе Windows, определение будет пропущено.

Используемые в данной области видимости условия могут быть также инвертированы для предоставления альтернативного набора объявлений, который будет обработан только если начальное условие ложно. Например, предположим, мы хотим обработать что-либо на всех платформах за исключением Windows. Мы можем добиться этого инвертированием области видимости, например так:

Области видимости могут быть вложенными для объединения более чем одного условия. Например, если вы хотите включить отдельный файл для определенной платформы только если разрешена отладка, тогда напишите следующее:

Чтобы избежать написания множества вложенных областей видимости вы можете вложить их используя оператор :. Вложенные области видимости в примере выше можно переписать следующим образом:

Вы также можете использовать оператор : для выполнения отдельной строки условных присваиваний; например:

В строке выше QT_DLL добавляется к переменной DEFINES только на платформе Windows. Как правило, оператор : ведет себя как логический оператор AND, объединяя вместе несколько условий, и требует истинности их всех.

Вы также можете предоставить альтернативные объявления внутри области видимости используя область видимости else. Каждая область видимости else обрабатывается если условия для предшествующих областей видимости были ложными. Это позволяет вам писать сложные тесты, комбинируя с другими областями видимости (разделенные оператором : как показано выше). Например:

Конфигурация и области видимости

Значения, сохраненные в переменной CONFIG, специально обрабатываются для qmake. Каждое из возможных значений может быть использовано в качестве условия для области видимости. Например, список значений, содержащихся в CONFIG, может быть расширен значением opengl:

В результате этой операции все области видимости, которые проверяют на opengl, будут обработаны. Мы можем использовать эту возможность чтобы дать финальному исполняемому файлу соответствующее имя:

Эта возможность облегчает изменение конфигурации проекта без потери всех пользовательских настроек, которые могут понадобиться для определенной конфигурации. В вышеприведенном коде обрабатываются объявления в первой области видимости, а финальный исполняемый файл будет называться application-gl. Однако, если opengl не указано, взамен будут обрабатываться объявления во второй области видимости, а финальный исполняемый файл будет называться application.

Так как можно поместить ваши собственные значения в строку CONFIG, это предоставляет вам удобный способ для настройки файлов проекта и тонкой настройки генерируемых Make-файлов.

Значения области видимости платформы

В добавление к значениям win32, macx и unix, используемым во многих условиях области видимости, с помощью областей видимости можно проверять различные другие встроенные значения, зависящие от платформы и компилятора. Они базируются на спецификациях платформ, предоставленных в каталоге Qt mkspecs. Например, следующие строки из файла проекта показывают текущую используемую спецификацию и проверяют на спецификацию linux-g++:

Вы можете проверить на все остальные комбинации платформа-компилятор, если спецификация имеется в каталоге mkspecs.

Переменные

Многие переменные, используемые в файлах проекта, являются специальными переменными, которые использует qmake при генерации Make-файлов, например, DEFINES, SOURCES и HEADERS. Вы можете создавать переменные для своих нужд; qmake создает новые переменные с заданным именем когда встретит присваивание этому имени. Например:

Не имеется ограничений на то, что вы можете делать со своими переменными, поскольку qmake будет их игнорировать пока при обработке области видимости не понадобится их вычислить.

Вы также можете присвоить значение текущей переменной, к имени которой добавлен префикс $$, переменной с другим именем. Например:

Теперь переменная MY_DEFINES содержит то, что есть в переменной DEFINES на этот момент в файле проекта. Это эквивалентно:

Второе представление позволяет вам добавлять содержимое переменной к другому значению без их разделения пробелом. Например, следующим обеспечивается то, что у финального исполняемого файла будет заданное имя, которое включает используемый шаблон проекта:

Переменные можно использовать для сохранения содержимого переменных окружения. Их можно вычислять во время запуска qmake или включить в сгенерированный Make-файл для вычисления при сборке проекта.

Для получения содержимого значения окружения при запуске qmake используйте оператор $$(. ):

В вышеприведенном присваивании значение переменной окружения PWD читается при обработке файла проекта.

Для получения содержимого значения окружения в тот момент, когда обрабатывается сгенерированный Make-файл, используйте оператор $(. ):

В вышеприведенном присваивании, значение PWD читается непосредственно при обработке файла проекта, но $(PWD) присваивается DESTDIR в сгенерированном Make-файле. Это делает процесс сборки более гибким до тех, пока переменная окружения корректно установлена при обработке Make-файла.

Специальный оператор $$[. ] может быть использован для получения доступа к различным опциям конфигурирования, которые были установлены при сборке Qt:

Доступность переменных с помощью этого оператора обычно используется для разрешения интеграции с Qt сторонних подключаемых модулей и компонентов. Например, подключаемый модуль Qt Designer можно установить рядом со встроенными подключаемыми модулями Qt Designer‘а, если в его файле проекта сделано следующее объявление:

Функции обработки переменной

qmake предоставляет набор встроенных функций для обработки содержимого переменных. Эти функции обрабатывают переданные им аргументы и возвращают в качестве результата значение или список значений. Для того чтобы присвоить переменной результат, необходимо использовать оператор $$ с этим типом функции таким же образом, как присваивается содержимое одной переменной другой:

Этот тип функции должен использоваться с правой стороны присваиваний (т.е., в качестве операнда).

Можно определить ваши собственные функции для обработки содержимого переменных. Такие функции можно определить следующим образом:

В следующем примере функция получает имя переменной как единственный аргумент, извлекает список значений из переменной с помощью встроенной функции eval() и составляет список файлов:

Условные функции

qmake предоставляет встроенные функции, которые можно использовать в качестве условий при написании областей видимости. Эти функции не возвращают значения, но вместо этого служат признаком «успеха» или «неудачи»:

Этот тип функции используется только в условных выражениях.

Вы можете определить собственные функции для предоставления условий для областей видимости. В следующем примере проверяется, существует ли каждый файл в списке и возвращается true если все они существуют, или false — если нет:

Добавление новых функций конфигурации

qmake позволяет вам создавать собственные функции, которые можно включать в файлы проекта, добавив их имена в список значений, задаваемых переменной CONFIG. Функции — это коллекции пользовательских функций и определений в файлах .prf, которые могут постоянно находиться в одном из стандартных каталогов. Размещение этих каталогов описывается в нескольких местах, а qmake при поиске файлов .prf проверяет каждое из них в следующем порядке:

  1. В каталоге, включенном в переменную окружения QMAKEFEATURES; содержит список каталогов, разделенных двоеточием.
  2. В каталоге, включенном в переменную свойства QMAKEFEATURES; содержит список каталогов, разделенных двоеточием.
  3. В каталоге функций, находящемся внутри каталога mkspecs. Каталоги mkspecs могут располагаться внизу всех каталогов, включенных в переменную окружения QMAKEPATH (список каталогов, разделенных двоеточием). ($QMAKEPATH/mkspecs/ )
  4. В каталоге функций, находящемся внизу каталога, предоставляемого переменной окружения QMAKESPEC. ($QMAKESPEC/ )
  5. В каталоге функций, находящемся в каталоге data_install/mkspecs. (data_install/mkspecs/ )
  6. В каталоге функций, который существует на том же уровне, что каталог указанный в переменной окружения QMAKESPEC. ($QMAKESPEC/../ )

В следующих каталогах функций производится поиск файлов функций:

  1. features/unix, features/win32 или features/macx, в зависимости от используемой платформы
  2. features/

Например, рассмотрим следующее присваивание в файле проекта:

С этим добавлением к переменной CONFIG, qmake будет искать файл myfeatures.prf в местах, перечисленных выше после завершения разбора вашего файла проекта. На Unix системах будет разыскиваться следующий файл:

  1. $QMAKEFEATURES/myfeatures.prf (для каждого каталога, перечисленного в переменной окружения QMAKEFEATURES)
  2. $$QMAKEFEATURES/myfeatures.prf (для каждого каталога, перечисленного в переменной окружения QMAKEFEATURES)
  3. myfeatures.prf (в корневом каталоге проекта)
  4. $QMAKEPATH/mkspecs/features/unix/myfeatures.prf и $QMAKEPATH/mkspecs/features/myfeatures.prf (для каждого каталога, перечисленного в переменной окружения QMAKEPATH)
  5. $QMAKESPEC/features/unix/myfeatures.prf и $QMAKESPEC/features/myfeatures.prf
  6. data_install/mkspecs/features/unix/myfeatures.prf и data_install/mkspecs/features/myfeatures.prf
  7. $QMAKESPEC/../features/unix/myfeatures.prf и $QMAKESPEC/../features/myfeatures.prf

Замечание: Имена файлов .prf должны быть в нижнем регистре.

Мастер Йода рекомендует:  Преобразование Фурье самый подробный разбор
Добавить комментарий