Qmake копирование файлов после сборки

Обновлено: 04.07.2024

Как я могу скопировать файл из моего проекта в выходной каталог с qmake?

Вы можете использовать функцию qmake для повторного использования:

затем использовать его следующим образом:

Если вы используете делайте установки, вы можете использовать устанавливает переменную к qmake. Вот пример:

затем выполните установка .

В Qt 5.6 добавлено это как недокументированная функция:

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

Список файлов, которые вы хотите скопировать, в ее.члены файлы:

Укажите путь в .член путь :

Дополнительно можно указать базовый путь для отсечения от путей источник:

Она в основном работает путем делать такие же вещи, как и многие другие ответы здесь. См. file_copies.ПРФ для подробностей.

Интерфейс очень похож на то, что для устанавливает .

Создайте файл `copy_files.ПРФ в один из путей, который использует qmake для особенности конфигурации. Файл должен выглядеть так:

Как это работает

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

Затем мы определяем дополнительные цели в Makefile copy_files.печенье , который зависит от compiler_copy_files_make_all цели` . Последнее-это название мишени, которая qmake генерирует за дополнительную компилятора, который мы определили в первом шаге. Это означает, что когда copy_files в .целевой печенье` будет построен, это будет вызывать дополнительную компилятор для копирования файлов.

Мы указываем команду для выполнения этой цели, которая будет "трогать" copy_files файлов.печенье и compiler_copy_files_make_all . Прикасаясь эти файлы, мы гарантируем, что делают не будет пытаться снова скопировать файлы, если их метки времени более поздней, чем коснулся файлов. Наконец, мы добавляем copy_files.печенье в список зависимостей сделать все` цель.

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

Скажите, например, из этот ответ :

Переменные % и % должны быть определенным, чтобы сделать эту работу. Хорошо, с % проблем нет: просто . . Но как я могу получить % ?

EDIT1

Скажем, у меня есть проект my_project здесь:

Итак, путь сборки релиза таков: /path/to/my_project-build-Desktop-release ,

путь отладочной сборки: /path/to/my_project-build-Desktop-debug

У меня есть файлы, которые нужно скопировать в каталог назначения здесь: /path/to/my_project/copy_to_install_dir

Итак, я хочу, чтобы все файлы из /path/to/my_project/copy_to_install_dir были скопированы в /path/to/my_project-build-Desktop-release когда я делаю релиз сборки. И то же самое для отладочной сборки.

Я не могу найти переменную, которая содержит полный путь назначения, т. е. /path/to/my_project-build-Desktop-release для отладочной сборки.

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

EDIT2

Точное решение для будущих читателей:

Это то, что мы используем в QtSerialPort:

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

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

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

Просто чтобы дать грубый пример различия этих двух переменных с реальным сценарием, здесь вы можете найти то, что мы делаем в QtSerialPort:

где первый является корнем исходного проекта, а второй - каталогом сборки. Они могут быть одинаковыми, но во многих случаях это не так, например при сборке через QtCreator только для одного из них.

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

Где required_files необходимо заменить на ваш правильный путь. $$PWD - путь к текущему файлу .pro , вы можете не требовать этого.

Примечание . Я нашел это решение здесь . Я рекомендую прочитать всю статью, поскольку она объясняет, как это работает.

Имея удовольствие потратить на это несколько часов, я решил поделиться своими выводами по этому вопросу. Это в модифицированном варианте метода Пагляна здесь . Так как я использую Windows (без MINGW), этот метод не работает. Итак, вот модифицированный вариант:

Поскольку это делает его кроссплатформенным, вы, конечно, также можете использовать этот метод в Linux, MacOS или что-то еще. Обратите внимание, что я копирую один файл, поэтому вместо $(COPY_DIR) я использую $(COPY_FILE) . Адаптируйте по мере необходимости.

Если вы хотите, чтобы файлы копировались по точному пути, где заканчивается двоичный файл (поскольку двоичный файл окажется в подпапке $$ OUT_PWD (выпуск debug или , по крайней мере, при сборке с помощью Qt Creator с MSVC 14 /cdb.exe /Code :: Blocks Makefiles configuration) вам нужно это:

Помните, что даже если двоичный файл попадает в подпапку, QtCreator выполняет двоичный файл из $$OUT_PWD , поэтому он ожидает найти файловые ресурсы в $$OUT_PWD , а НЕ в подкаталоге debug . Это означает, что вы, например, не можете выполнить QIcon("archive.jpg") и ожидать, что он найдет его помимо исполняемого файла.

Если вы решите, что это то, что вам нужно, вам, очевидно, нужно отредактировать последний аргумент $$(COPY_FILE) (в .pro) следующим образом : \"$$shell_path($$OUT_PWD)\\$$VARIANT\"

Еще одна вещь, на которую следует обратить внимание, это то, что (в любом случае, в моем случае) Qt Creator (4.0.1) не всегда создает файл .pro, так как он не обнаруживает никаких изменений в конфигурации, поэтому необходимо отразить вышеуказанные изменения в Makefile (и, таким образом, запускается при сборке вашего проекта) вы должны фактически собрать .pro вручную, запустив Build->run qmake из меню приложения , Чтобы все прошло гладко, посмотрите на вывод компиляции, нажав Alt + 4 (в любом случае в Windows).

Как скопировать файл из моего проекта в выходной каталог с помощью qmake?

Я собираюсь в Linux, но в будущем я скомпилирую его на Mac и Windows.

Вот пример из одного из наших проектов. Он показывает, как копировать файлы в DESTDIR для Windows и Linux.

Вы можете использовать функцию qmake для повторного использования:

то используйте его следующим образом:

Если вы используете make install, вы можете использовать переменную INSTALLS в qmake. Вот пример:

затем выполните make install .

Я нашел, что мне пришлось изменить ответ, полученный sje397. для Qt5 Beta1 вместе с QtCreator 2.5.2. Я использую этот script для копирования qml файлов в целевой каталог как шаг добавления после завершения сборки.

Мой .pro файл имеет следующий код

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

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

Как это работает

Затем мы определяем дополнительный файл makefile copy_files.cookie , который зависит от цели compiler_copy_files_make_all . Последний - это имя цели, которую qmake генерирует для дополнительного компилятора, который мы определили на первом этапе. Это означает, что когда цель copy_files.cookie построена, она будет вызывать дополнительный компилятор для копирования файлов.

Мы указываем команду, которая будет выполняться этой целью, которая будет touch файлами copy_files.cookie и compiler_copy_files_make_all . Прикоснувшись к этим файлам, мы гарантируем, что make не будет пытаться копировать файлы снова, если их временные метки не являются более поздними, чем затронутые файлы. Наконец, мы добавим copy_files.cookie в список зависимостей цели make all .

Как использовать его

В вашем .pro файле добавьте COPY_FILES в переменную CONFIG :

Затем добавьте файлы в переменную COPY_FILES :

Qt 5.6 добавил это как недокументированную особенность:

Придумайте имя, чтобы описать файлы, которые вы хотите скопировать:

Перечислите файлы, которые вы хотите скопировать, в .files :

Укажите целевой путь в .path :

При желании укажите базовый путь, который нужно обрезать из исходных путей:

Это в основном работает, делая то же самое, что и многие другие ответы здесь. Смотрите file_copies.prf для подробностей.

Интерфейс очень похож на интерфейс INSTALLS .

Как дополнение к Jake answer и @Phlucious comment, можно использовать функцию qmake defineReplace , которая лучше подходит для этого варианта использования. После использования приведенного примера я столкнулся с проблемой, когда qmake пропустил последнее действие ссылки ссылки, которое я добавил. Это может быть проблемой при экспорте переменной, хотя контент выглядел довольно хорошо все время. Короче говоря, здесь есть модифицированный код

Эта общая функция копирования может использоваться некоторыми удобными функциями, такими как

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

Но теперь обратите внимание на разницу в вызове

Как вы можете видеть, вы можете присоединить возвращенную команду к QMAKE_PRE_LINK для еще большей гибкости.

Во-первых, определите где-нибудь ниже (из среды XD ), например, в файле functions.prf :

и использовать его в своем проекте, как:

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

Полный скрипт xd_functions.prf

Но когда вам нужно что-то вроде copyFileLater(source, destination) , чтобы копировать файлы только после завершения сборки, тогда рассмотрите возможность использования приведенного ниже кода (который XD из фреймворка XD под Apache 2.0 ):



Примечание(17.06.2013): синтаксис примеров в статье не соответствует последним версиям. Сверяйтесь с документацией. Также в марте был выпущен Qt Creator 2.7 с поддержкой QBS.
Не так давно команда разработчиков Qt представила новую систему сборки — QBS. Разумеется, основной реакцией было «Да чем вас QMAKE не устраивал», «Просто адаптируйте CMAKE», «Ещё одна система сборки [xkcd, стандарты]». Обещанные преимущества новой системы: гибкость, понятный синтаксис для всех разработчиков (QML — javascript-подобный декларативный язык), скорость билдов (чистых и инкрементальных), а также лёгкая расширяемость.
Всё это мы где-то уже слышали, поэтому в данной статье мы попытаемся разобраться, как разработчики пришли к этой системе, рассмотрим простейшие примеры, изучим основные конструкции и посмотрим, какая поддержка на уровне IDE присутствует на настоящий момент.

История

Сейчас мы вместе постараемся повторить путь Йорга Борнемана (Jörg Bornemann), разработчика QBS.

Критика make (и производных)
  • Традиционная для UNIX система сборки make выдает непозволительно долгое время сборки для больших проектов (особенно для инкрементальных сборок);
  • Использование рекурсивого вызова make из корневой директории приводит к нарушениям зависимостей между модулями, для устранения которого приходится запускать сборку два или три раза (и увеличение времени сборки, естественно);
  • Использование единого makefile устраняет недостатки, но поддержка становится невыносимой. О какой-либо достаточной поддержки изменений makefile с помощью IDE речи не идёт.
  • Портируемость make сильно раздута, так как make работает не сам по себе, в makefile могут быть указаны десятки других утилит, которые специфичны для платформы;
  • Масштабируемость ужасна, при использовании рекурсивного make (то же мнение, что в предыдущей статье), и недостаточна при использовании include или других расширений. В частности, производительность сборки падает очень быстро.
  • Неочевидные и откровенно ущербные элементы языка (чего стоят только ifeq, ifneq, ifdef, и ifndef)
  • Проблемы типов (работа только со строками)
  • Плохое разрешение зависимостей в случае изменения опций командной строки
  • Проблемы с одновременным запуском и распараллеливанием
  • Легко «убить» дерево сборки внезапной остановкой программы.
  • И много других мелких косяков, которые свидетельствуют о неподходящей архитектуре под современные нужды (по мнению автора).

В короткой заметке Ian Lance Taylor, 2007 г. рассмотрен основной недостаток Cmake как замены Make — Он. Слишком. Сложен. Это адская смесь нескольких языков, поддерживать её (для действительно сложных систем) могут только гуру разработки и отладки (отлаживать её тоже проблематично). Ещё одним недостатком является то, что за гибкость (даже ГИБКОСТЬ), приходится расплачиваться потерей производительность в сгенерированных скриптах.

Что не так с QMake?

В инфраструктуре Qt на сегодняшний день широко используется система сборки Qmake, которая поддерживается официально и все ещё дорабатывается. Зачем же возникла надобность «just another one» системы сборки?

    Свой, самобытный синтаксис языка.

Попробуйте посмотреть на QTDIR/mkspecs/features/exclusive_builds.prf:

  • Она должна быть ОЧЕНЬ быстрой (незаметное время чтобы произвести stat() всех файлов);
    Изменение узла где-то в глубине дерева сборки не должно приводить к изменению конфигурации всего дерева;
  • У неё должен быть простой и понятный язык, который может быть легко понят людьми и обслужен скриптами;
    Язык должен быть хорошо специализирован;
    Он должен быть декларативным в своей структуре, с небольшими императивными фрагментами, жёстко изолированными от остальных;
    Язык должен основываться на свойствах, а не на командах. Никаких CFLAGS. (cmake на полпути к этому);
  • Должна быть полная поддержка модульности. Также любой подпроект должен иметь возможность легко отделяться от родительского (и присоединяться к другому). Т. е., грубо говоря, взяли папку с конфигурацией сборки, вставили в другой проект -там тоже все хорошо собирается (без учёта зависимостей конечно);
  • Чёткая и ясная поддержка для IDE;
  • Должная быть возможность сборки разных конфигураций под разные платформы в один проход.

Представляем «спасательный круг» — Qt Build System

  • Декларативность — используется QML синтаксис;
  • Расширяемость — есть возможность писать свои модули для сборки, либо кодогенераторы и т. п. (ниже мы попробуем написать свой модуль для сборки проектов Delphi);
  • Скорость;
  • Сборка напрямую — это не qmake, это не «посредник». Qbs сама вызывает компиляторы, компоновщик, и что там еще понадобится.
Начнём пробовать!

Автор советует собрать qbs из исходников, но можно иметь ввиду, для пользователей win и linux есть бинарные сборки
win — собрано под MSVC2010. Я бы тоже посоветовал собрать версию из git ( у меня проблемы были с плагинами и MOC).
В бинарном виде qbs зависит от библиотек QtCore и QtScript (+Concurrent для Qt5)
Создадим Hello World проект на С++:
main.cpp


Создадим также минимальный проект на qbs:
hello.qbp

LINUX:
1. Открываем в текущей папке шелл.
2. Добавляем путь, куда вы распаковали/собрали qbs, в PATH (вернее, bin папку)
PATH=

/qbs/bin/:$PATH
3. запускам qbs:
qbs

После этого программа сборки запустит разбор проекта и соберет в папке build/debug исполняемый файл (ну мы же не указали пока папку назначения?)
WINDOWS:
4. Поскольку под Windows, как правило компилятор и qt не находятся в PATH, qbs может попросить вас запустить «qbs platform probe», что необходимо сделать.
5. затем возможно, понадобится запустить qbs config update или подобное (если он попросит, возможно это исправили уже).
6. после этого при запуске qbs [build] — вы получите собранный бинарник «HelloWorld.exe»

Продолжаем изучать

Теперь попробуем освоить сборку чего-то более сложного, и заодно, разобраться с языком.
Для начала, создадим новую папку и скопируем туда папки «2dpainting» и «collidingmice» из папки examples с Qt.
Почему сразу два? Мы создадим конфигурацию для сборки сразу двух продуктов.
Продукт — это целевой «выход» системы сборки, подобие «.pro» файла при сборке Qmake. В одном проекте qbs может быть несколько продуктов.
Для начала создадим проект «examples.qbp»

Откроем консоль и попробуем собрать, выведется ошибка «ERROR: Error while setting up build environment: qt.core.incPath not set. Set qt.core.incPath or qt.core.path in your profile. »
Закроем пока глаза на не слишком юзер-френдли способ конфигурации, и создадим файл «qbs.config» с таким содержимым (WINDOWS):


либо под LINUX (ubuntu):

и запустить qbs config --import qbs.config
После этого qbs нормально сможет собрать проект и поместит выходной файл в папку build/debug.
Для того чтобы собрать проект в релиз, выполните «qbs build release».
Для очистки всех файлов сборки (т. е. Папки «build») выполните «qbs clean».
Теперь попробуем организовать расширяемую структуру для двух проектов. Создадим в подкаталогах «2dpainting» и «collidingmice» файлы-тёзки своих каталогов с расширением «.qbs» с таким содержимым:

Т.е. мы разбиваем код на независимые продукты, которые могут собираться параллельно. Внесём изменения в examples.qbp:


Можете снова запустить «qbs». Обратите внимание, для «.qrc» файла будет автоматически вызван «rcc» и все это слинковано вместе. Все файлы при этом указываются одним списком, без разделения на HEADERS, SOURCES и т. д., как было в qmake.

Как это все работает?

Для начала рекомендую бегло ознакомиться со справкой
Основные концепции языка: Проект (Project), Продукт (Product), Артефакт (Artifact), Модуль (Module), Правило (Rule), Группа(Group), Зависимость (Depends), Тег (Tag).
Продукт — это аналог pro или vcproj, т. е. одна цель для сборки.
Проект — это набор ваших продуктов вместе с зависимостями, воспринимаемый системой сборки как одно целое. Один проект — один граф сборки.
Тег — система классификации файлов. Например «*.cpp» => «cpp»
Правило — Преобразование файлов проекта, отмеченных определенными тегами. Генерирует другие файлы, называемые Артефактами. Как правило, это компиляторы или другие системы сборки.
Артефакт — файл, над который является выходным для правила (и возможно, входным для други правил). Это обычно «obj», «exe» файлы.
У многих QML-объектов есть свойство condition, которое отвечает за то, будет собираться он или нет. А если нам необходимо разделить так файлы? Для этого их можно объединить в группу (Group)

примерно таким образом.

Что же дальше?

Заключение

  • Удобный и понятный формат конфигов сборки
  • Высокую скорость
  • Чёткую модульную архитектуру
  • Наличие большого количества багов (это ещё не альфа);
  • Отсутствие поддержки IDE (ждем в Qt Creator);
  • Отсутствие системы сборки пакетов, инсталляторов (в планах).
  1. Создание собственного модуля (он включён в архив с примерами);
  2. Написание правил для сборки;
  3. Создание js-модулей и их включение;
  4. Создание своих типов продуктов;
  5. Работа с глобальным конфигом и конфиги модулей;
  6. Написание своего плагина (для парсинга зависимостей .drpoj файла).

Ссылки

Примечание: Qt Build Salvation (Спасение для сборки Qt) — внутреннее имя QBS, в README дерева исходников.

Читайте также: