Qbs Quick Reference/ru: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
(Tranlation. Work in progress.)
(Translating .pro and .pri)
 
(10 intermediate revisions by the same user not shown)
Line 99: Line 99:
=== DEFINES = MACRO ===
=== DEFINES = MACRO ===


Use the following: Note that in order to reference cpp.defines you must specify a dependency on the cpp module.
Используйте следующие примеры, но обратите внимание, что конструкцию '''cpp.defines''' можно использовать только в cpp-модуле.
<code>Depends { name: 'cpp' }
<code>Depends { name: 'cpp' }
Line 105: Line 105:
</code>
</code>


The cpp module might define default preprocessor macros. For example on Windows UNICODE is predefined.
В cpp-модуле можно определить предпроцессорные макросы используемые по умолчанию. Например в Windows'е заранее определён UNICODE.
These are stored in the property cpp.platformDefines.
Он хранится в свойстве '''cpp.platformDefines'''.
To override these macros do:
Чтобы переопределить макрос, пишем:
<code>Product {
<code>Product {
  Depends { name: 'cpp' }
  Depends { name: 'cpp' }
Line 115: Line 115:
</code>
</code>


To add macros within a group, you need to use outer.concat rather than base.concat(), because you are adding additional macros to what is specified in the outer scope:
Для добавления макроса внутри группы, нужно использовать '''outer.concat''' вместо '''base.concat''', так как дополнительные макросы вы указываете во внешней области:


<code>Product {
<code>Product {
  Depends { name: 'cpp' }
  Depends { name: 'cpp' }
  …
  …
  cpp.defines: ['MACRO_EVERYWHERE'] // This is defined for all files in this product (unless a group overrides it!)
  cpp.defines: ['MACRO_EVERYWHERE'] // Это определено для всех файлов в продукте (если группа не переопределит это!)
  Group {
  Group {
   cpp.defines: outer.concat('MACRO_GROUP')
   cpp.defines: outer.concat('MACRO_GROUP')
   files: groupFile.cpp
   files: groupFile.cpp
   // MACRO_GROUP is only defined in groupFile.cpp
   // MACRO_GROUP определён только для файла groupFile.cpp
   // MACRO_EVERYWHERE is also defined in groupFile.cpp because of the outer.concat
   // MACRO_EVERYWHERE тоже определён в groupFile.cpp, из-за использования outer.concat
  }
  }
}
}
</code>
</code>


cpp.defines statements inside a group only apply to the files in that group - therefore you cannot use a group to include a bunch of files and globally-visible macros - the macros must go in a Properties block at the same level as the group if they need to be visible to files outside the group:
cpp.defines выражение применяется к файлам только в этой группе, поэтому вы не можете использовать группу для добавления глобально-видимых макросов - такие макросы должны определяться в объекте '''Properties''' расположенном на том же уровне, что и группа, если макросу нужно быть видимым за пределами группы:


<code>Product {
<code>Product {
Line 140: Line 140:
  }
  }


property stringList commonDefines: ["ONE", "TWO"]
property stringList commonDefines: ["ONE", "TWO"]
  Properties {
  Properties {
   condition: supportFoobar === true
   condition: supportFoobar === true
Line 146: Line 146:
  }
  }
  Properties {
  Properties {
   cpp.defines: commonDefines // else case for the Properties chain
   cpp.defines: commonDefines // блок else для цепочки объектов Properties
  }
  }
}
}
Line 157: Line 157:
=== CONFIG -= Qt ===
=== CONFIG -= Qt ===


Just don't declare Qt as a dependency. Probably you'd want:
Просто не добавляйте зависимость от Qt. Возможно вам нужен просто C++:


<code>Depends { name: "cpp" }</code>
<code>Depends { name: "cpp" }</code>
Line 163: Line 163:
=== RC_FILE ===
=== RC_FILE ===


Just add the file to the "files" list.
Просто добавьте файл к остальному списку в свойстве '''files'''.


=== QMAKE_INFO_PLIST ===
=== QMAKE_INFO_PLIST ===
Line 172: Line 172:
=== ICON ===
=== ICON ===


Not yet implemented. See [https://bugreports.qt.io/browse/QBS-73 QBS-73].
К сожалению ещё не реализовано. Смотрим [https://bugreports.qt.io/browse/QBS-73 QBS-73].


=== TEMPLATE = subdirs ===
=== TEMPLATE = subdirs ===
Line 187: Line 187:


=== CONFIG = ordered ===
=== CONFIG = ordered ===
This is one of the most misused qmake features, and there is no equivalent to it in qbs.
 
Instead, just like you are supposed to do it in qmake, an ordering is introduced via dependencies:
Дурная фишка qmake, которой нет в qbs.
Очередь сборки определяется зависимостями.
 
<code>
<code>
CppApplication {
CppApplication {
Line 195: Line 197:
}
}
</code>
</code>
The "myapp" product depends on "mylib" and is therefore built after it.
 
"myapp" зависит от "mylib", потому и соберётся после него.
 
=== DESTDIR ===
=== DESTDIR ===


Use the destinationDirectory property:
Используйте свойство '''destinationDirectory''':


<code>
<code>
Line 208: Line 212:
</code>
</code>


Using it is not recommended, however; you should rather use the installation mechanism (see below).
Но это не рекомендуется. Вместо этого лучше использовать механизм установки (смотрим дальше).
 
=== QML_IMPORT_PATH ===
=== QML_IMPORT_PATH ===


Used only for QtCreator QML syntax highlighting. Inside a 'Product' (or 'Application' / 'CppApplication') item, create a "qmlImportPaths" property:
Используется только для подсветки QML-синтаксиса QtCreator'ом. Внутри продукта ('Product', 'Application', 'CppApplication' и т.п.) создайте свойство '''qmlImportPaths''':


<code>Product {
<code>Product {
Line 217: Line 222:
  readonly property stringList qmlImportPaths: [sourceDirectory + "/path/to/qml/"]
  readonly property stringList qmlImportPaths: [sourceDirectory + "/path/to/qml/"]
}</code>
}</code>
=== 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 234: 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 243: 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 263: Line 272:
  }
  }


—hellocrazyworld.qbs—
-- файл hellocrazyworld.qbs --
  CrazyProduct {
  CrazyProduct {
   craziness: "enormous"
   craziness: "enormous"
Line 271: 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 283: 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 300: 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
}