Qbs Quick Reference/ru: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
(Translating .pro and .pri)
 
(3 intermediate revisions by the same user not shown)
Line 225: Line 225:
=== message(), warning(), error() ===
=== message(), warning(), error() ===


You can use the JavaScript function print for printing messages and throw exceptions on the right hand side of property bindings.
Вы можете использовать JavaScript-функцию '''print''' для вывода сообщений и '''throw''' для генерации исключений во время определения значений свойств.


<code>Product {
<code>Product {
  name: {
  name: {
   print("—-> now evaluating the product name");
   print("—-> устанавливаем название продукта");
   return "theName";
   return "theName";
  }
  }
  Depends {name: "cpp"}
  Depends {name: "cpp"}
  cpp.includePath: {
  cpp.includePath: {
   throw "I don't know. Something bad happened."
   throw "ХЗ. Что-то плохое приключилось"
   return [];
   return [];
  }
  }
Line 240: Line 240:


=== QTPLUGIN.platforms = qminimal ===
=== QTPLUGIN.platforms = qminimal ===
Building static applications, often requires to link to static Qt plugins.
 
You can use the following syntax to let Qbs link to the requested plugins:
Собирая статическое приложение, часто надо ссылаться на статические Qt-плагины.
Вы можете использовать следующий код для того, чтобы Qbs сослался на требуемые плагины:
 
<code>
<code>
Product{
Product{
Line 249: Line 251:
}
}
</code>
</code>
This leads to static linking of the plugins/platforms/qminimal plugin into the application.


=== Others not mentioned above ===
Это приводит к статической компоновке с plugins/platforms/qminimal плагинами в приложении.
 
=== Остальное, не упомянутое выше ===


Either I've missed them, or they're not yet implemented.
Либо Я упустил это, либо оно ещё не реализовано.


== .pro and .pri ==
== .pro and .pri ==


The top-level .qbs file contains the "Project" definition. A project can contain multiple products, so you may find that multiple .pro files can be expressed in a single .qbs. The subdirs pattern will typically convert to a single .qbs containing references to multiple .qbs files. Each .qbs file would then define a single product or sub-project.
Самый верхний по уровню .qbs-файл содержит проект (Project объект). Проект может содержать множество продуктов, а множество .pro-файлов можно выразить одним .qbs-файлом. Обычно подпапки объединяют одним .qbs ссылаясь на множество .qbs-файлов. Один .qbs-файл определяет один продукт или подпроект.


.qbs files can also be used like .pri files in that a top-level .qbs can include sections defined in another .qbs. For example:
.qbs-файлы можно использовать как .pri-файлы и .qbs верхнего уровня может содержать секции, определённые в других .qbs. Например:


<code>
<code>
—CrazyProduct.qbs—
-- файл CrazyProduct.qbs --
  import qbs.base 1.0
  import qbs.base 1.0


Line 269: Line 272:
  }
  }


—hellocrazyworld.qbs—
-- файл hellocrazyworld.qbs --
  CrazyProduct {
  CrazyProduct {
   craziness: "enormous"
   craziness: "enormous"
Line 277: Line 280:
</code>
</code>


.qbs files in the same directory as the top-level .qbs file are picked up automatically. Others must be explicitly imported and named using an "import … as …" statement:
.qbs-файлы лежащие в той же директории, ровно как и .qbs-файл верхнего уровня подхватываются автоматически. Остальные же необходимо импортировать и именовать вручную, используя "import … as …" структуру:


<code>
<code>
Line 289: Line 292:
</code>
</code>


 
Это позволяет подхватывать дополнительные группы с файлами, как с .pri-файлами, импортируя .qbs с определением группы и декларируя эту группу в продукте.
It is also possible pick groups of source files externally like with .pri files, by importing a .qbs with a Group defined in it and declaring this imported group inside the Product declaration.


<code>
<code>
-- in external.qbs file--
-- файл external.qbs --
import qbs
import qbs
Group {
Group {
  files:["file1.cpp", "file2.cpp"]
  files:["file1.cpp", "file2.cpp"]
}
}
-- in product.qbs file--
 
-- файл product.qbs --
import qbs
import qbs
import "external.qbs" as SourceGroup
import "external.qbs" as SourceGroup
Line 306: Line 309:
}
}
</code>
</code>
If opened with qtcreator, files from external.qbs will be visible in a group belonging to SomeProduct
 
Если открыть в QtCreator'е, файлы из external.qbs будут видимы в группе продукта SomeProduct.


== Conditionals ==
== Conditionals ==

Latest revision as of 12:10, 6 February 2017

En Ar Bg De El Es Fa Fi Fr Hi Hu It Ja Kn Ko Ms Nl Pl Pt Ru Sq Th Tr Uk Zh

Вступление

Qbs - это система сборки нового поколения, впервые представленная в Qt Blog. Эта страница задумана как краткое руководство к переводу проектов из qmake .pro в .qbs. Это руководство не заменяет официальную документацию, а скорее кратко описывает текущее состояние функциональности qbs с упором на переход с qmake'а.

На момент написания этого руководства в qbs'е реализован не весь функционал из qmake'а. На подобные функции приложена ссылка на Qt Bug Tracker.

Qbs руководство

Полное руководство по Qbs можно посмотреть в Qt Documentation.

Qbs эквиваленты

TEMPLATE = app

Используйте Application или CppApplication как продукт:

CppApplication {
 name: "helloworld"
 files: "main.cpp"
 
}

Что аналогично такой записи:

Product {
 name: "helloworld"
 type: "application"
 files: "main.cpp"
 Depends { name: "cpp" }
 
}


TEMPLATE = lib

Используйте DynamicLibrary как продукт:

DynamicLibrary {
 name: "mydll"
 files: ["stuff.cpp"]
 Depends { name: "cpp" }
 
}

TARGET = myappname

Используйте свойство name, см. примеры TEMPLATE выше.

HEADERS, SOURCES, FORMS, RESOURCES

Просто перечислите эти файлы в свойстве files:

files: ['thing.h', 'thing.cpp', 'thing.ui', 'myapp.qrc']

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

CONFIG = console

Application {
 name: "helloworld"
 files: "main.cpp"
 consoleApplication: true
 
}

CONFIG = designer_defines

DynamicLibrary {
 name: "myplugin"
 files: ["foo.cpp", ]
 Depends { name: "cpp" }
 cpp.defines: ["QDESIGNER_EXPORT_WIDGETS"]
 
}

QT = modulename

Добавьте объект Depends в продукт, например:

Product {
 Depends { name: "Qt.core" }
 // …или…
 Depends { name: "Qt"; submodules: ["core", "gui", "network"] }
}

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

DEFINES = MACRO

Используйте следующие примеры, но обратите внимание, что конструкцию cpp.defines можно использовать только в cpp-модуле.

Depends { name: 'cpp' }

cpp.defines: ['SUPPORT_COOL_STUFF']

В cpp-модуле можно определить предпроцессорные макросы используемые по умолчанию. Например в Windows'е заранее определён UNICODE. Он хранится в свойстве cpp.platformDefines. Чтобы переопределить макрос, пишем:

Product {
 Depends { name: 'cpp' }
 
 cpp.platformDefines: ['MY_SPECIAL_DEFINE', 'UNICODE']
}

Для добавления макроса внутри группы, нужно использовать outer.concat вместо base.concat, так как дополнительные макросы вы указываете во внешней области:

Product {
 Depends { name: 'cpp' }
 
 cpp.defines: ['MACRO_EVERYWHERE'] // Это определено для всех файлов в продукте (если группа не переопределит это!)
 Group {
  cpp.defines: outer.concat('MACRO_GROUP')
  files: groupFile.cpp
  // MACRO_GROUP определён только для файла groupFile.cpp
  // MACRO_EVERYWHERE тоже определён в groupFile.cpp, из-за использования outer.concat
 }
}

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

Product {
 Depends { name: 'cpp' }
 
 Group {
  condition: supportFoobar === true
  files: fooFile.cpp
 }

 property stringList commonDefines: ["ONE", "TWO"]
 Properties {
  condition: supportFoobar === true
  cpp.defines: commonDefines.concat("FOOBAR_SUPPORTED")
 }
 Properties {
  cpp.defines: commonDefines // блок else для цепочки объектов Properties
 }
}

INCLUDEPATH = dir

cpp.includePaths: [ '..', 'some/other/dir']

CONFIG -= Qt

Просто не добавляйте зависимость от Qt. Возможно вам нужен просто C++:

Depends { name: "cpp" }

RC_FILE

Просто добавьте файл к остальному списку в свойстве files.

QMAKE_INFO_PLIST

Set the "bundle.infoPlistFile" property of the bundle module.

Depends { name: "bundle" }

ICON

К сожалению ещё не реализовано. Смотрим QBS-73.

TEMPLATE = subdirs

Inside a "Project" item, use "references":

Project {
 references: [
  "app/app.qbs",
  "lib/lib.qbs"
 ]
}

CONFIG = ordered

Дурная фишка qmake'а, которой нет в qbs. Очередь сборки определяется зависимостями.

CppApplication {
    name: "myapp"
    Depends { name: "mylib" }
}

"myapp" зависит от "mylib", потому и соберётся после него.

DESTDIR

Используйте свойство destinationDirectory:

DynamicLibrary {
 name: "mydll"
 destinationDirectory: "libDir"
 
}

Но это не рекомендуется. Вместо этого лучше использовать механизм установки (смотрим дальше).

QML_IMPORT_PATH

Используется только для подсветки QML-синтаксиса QtCreator'ом. Внутри продукта ('Product', 'Application', 'CppApplication' и т.п.) создайте свойство qmlImportPaths:

Product {
 name: "myProduct"
 readonly property stringList qmlImportPaths: [sourceDirectory + "/path/to/qml/"]
}

message(), warning(), error()

Вы можете использовать JavaScript-функцию print для вывода сообщений и throw для генерации исключений во время определения значений свойств.

Product {
 name: {
  print("—-> устанавливаем название продукта");
  return "theName";
 }
 Depends {name: "cpp"}
 cpp.includePath: {
  throw "ХЗ. Что-то плохое приключилось"
  return [];
 }
}

QTPLUGIN.platforms = qminimal

Собирая статическое приложение, часто надо ссылаться на статические Qt-плагины. Вы можете использовать следующий код для того, чтобы Qbs сослался на требуемые плагины:

Product{
    name: "myapp"
    Depends { name: "Qt"; submodules: ["core", "gui", "widgets"] }
    Depends { name: "Qt.qminimal"; condition: Qt.staticBuild }
}

Это приводит к статической компоновке с plugins/platforms/qminimal плагинами в приложении.

Остальное, не упомянутое выше

Либо Я упустил это, либо оно ещё не реализовано.

.pro and .pri

Самый верхний по уровню .qbs-файл содержит проект (Project объект). Проект может содержать множество продуктов, а множество .pro-файлов можно выразить одним .qbs-файлом. Обычно подпапки объединяют одним .qbs ссылаясь на множество .qbs-файлов. Один .qbs-файл определяет один продукт или подпроект.

.qbs-файлы можно использовать как .pri-файлы и .qbs верхнего уровня может содержать секции, определённые в других .qbs. Например:

-- файл CrazyProduct.qbs --
 import qbs.base 1.0

 Product {
  property string craziness: "low"
 }

-- файл hellocrazyworld.qbs --
 CrazyProduct {
  craziness: "enormous"
  name: "hellocrazyworld"
  // …
 }

.qbs-файлы лежащие в той же директории, ровно как и .qbs-файл верхнего уровня подхватываются автоматически. Остальные же необходимо импортировать и именовать вручную, используя "import … as …" структуру:

import qbs.base 1.0
import "../CrazyProduct.qbs" as CrazyProduct
CrazyProduct {
 craziness: "enormous"
 name: "hellocrazyworld"
 // …
}

Это позволяет подхватывать дополнительные группы с файлами, как с .pri-файлами, импортируя .qbs с определением группы и декларируя эту группу в продукте.

-- файл external.qbs --
import qbs
Group {
 files:["file1.cpp", "file2.cpp"]
}

-- файл product.qbs --
import qbs
import "external.qbs" as SourceGroup
Product {
 name: "SomeProduct"
 SourceGroup {}
}

Если открыть в QtCreator'е, файлы из external.qbs будут видимы в группе продукта SomeProduct.

Conditionals

Instead of the qmake syntax of "windows { … }" or "macx:…", you specify a "condition" property in the relevant block. Conditionally-compiled files should be collected in a "Group" block, while platform-specific properties should go in a "Properties" block rather than being put in the main (outer) block:

Group {
 condition: qbs.targetOS.contains("windows")
 files: [
  "harddiskdeleter_win.cpp",
  "blowupmonitor_win.cpp",
  "setkeyboardonfire_win.cpp"
 ]
}

Properties {
 condition: qbs.targetOS.contains("linux")
 cpp.defines: outer.concat(["USE_BUILTIN_DESTRUCTORS"])
}

See the DEFINES section above for important information about how conditionals and cpp.defines interact.

C++ compiler options

Here is a selection of options that are supported. The full list can be found in share/qbs/modules/cpp/CppModule.qbs in the qbs source tree, these are some of the more useful:

cpp.optimization: "none" // or "fast"
cpp.debugInformation: true
cpp.staticLibraries: "libraryName"
cpp.dynamicLibraries: "libraryName"
cpp.frameworks: "frameworkName"
cpp.precompiledHeader: "myheader.pch"
cpp.warningLevel: "all" // or "none", "default"
cpp.treatWarningsAsErrors: true
cpp.cxxLanguageVersion // E.g. "c++11"

Note that setting things like cflags directly is discouraged (because they are compiler-dependent), and higher-level alternatives like cpp.optimization: "fast" should be used if available.

Installing files

Create a group containing the files, and set qbs.install and qbs.installDir:

Group {
 qbs.install: true
 qbs.installDir: "lib/myproj/"
 files: [
  "Menu.qml",
  "SomeImportantFile.bin"
 ]
}

For files generated by the build (e.g. an executable), you need to match them by their file tag:

Group {
 qbs.install: true
 qbs.installDir: "bin"
 fileTagsFilter: "application"
}

By default, installation happens automatically when building. The default installation root is called "install_root" and is located at the top level of the build directory. It can be overwritten by setting the qbs.installRoot property on the command line.

Command-line examples

64-bit:

qbs -f /path/to/project.qbs --products productname qbs.architecture:x86_64

"Magic" variables

Variables defined in various scopes, which may not be obvious:

qbs

This has lots of useful things in, such as: targetOS ("windows", "linux", "darwin", …); buildVariant ("debug", "release"); architecture ("x86", "x86_64", …)

project

Valid anywhere in your project, needed to refer to project properties from within a product:

Project {
 property string version: "1.0"

 Product {
  cpp.defines: ["PROJECT_VERSION=" + project.version]
 }
}

buildDirectory

The top-level build directory. By default will be a subdirectory in the directory where you invoked qbs from, whose name is derived from the current profile. It can also be explicitly specified via the -d option.

Module names

Modules that are declared as dependencies can be referred to by their name and their properties accessed. For example:

Product {
 Depends { name: "Qt.quick" }
 Qt.quick.qmlDebugging: false
}