Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.
Qbs Quick Reference/ru
Вступление
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
Just add the file to the "files" list.
QMAKE_INFO_PLIST
Set the "bundle.infoPlistFile" property of the bundle module.
Depends { name: "bundle" }
ICON
Not yet implemented. See QBS-73.
TEMPLATE = subdirs
Inside a "Project" item, use "references":
Project {
references: [
"app/app.qbs",
"lib/lib.qbs"
]
}
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:
CppApplication {
name: "myapp"
Depends { name: "mylib" }
}
The "myapp" product depends on "mylib" and is therefore built after it.
DESTDIR
Use the destinationDirectory property:
DynamicLibrary {
name: "mydll"
destinationDirectory: "libDir"
…
}
Using it is not recommended, however; you should rather use the installation mechanism (see below).
QML_IMPORT_PATH
Used only for QtCreator QML syntax highlighting. Inside a 'Product' (or 'Application' / 'CppApplication') item, create a "qmlImportPaths" property:
Product {
name: "myProduct"
readonly property stringList qmlImportPaths: [sourceDirectory + "/path/to/qml/"]
}
message(), warning(), error()
You can use the JavaScript function print for printing messages and throw exceptions on the right hand side of property bindings.
Product {
name: {
print("—-> now evaluating the product name");
return "theName";
}
Depends {name: "cpp"}
cpp.includePath: {
throw "I don't know. Something bad happened."
return [];
}
}
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:
Product{
name: "myapp"
Depends { name: "Qt"; submodules: ["core", "gui", "widgets"] }
Depends { name: "Qt.qminimal"; condition: Qt.staticBuild }
}
This leads to static linking of the plugins/platforms/qminimal plugin into the application.
Others not mentioned above
Either I've missed them, or they're not yet implemented.
.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 files can also be used like .pri files in that a top-level .qbs can include sections defined in another .qbs. For example:
—CrazyProduct.qbs—
import qbs.base 1.0
Product {
property string craziness: "low"
}
—hellocrazyworld.qbs—
CrazyProduct {
craziness: "enormous"
name: "hellocrazyworld"
// …
}
.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:
import qbs.base 1.0
import "../CrazyProduct.qbs" as CrazyProduct
CrazyProduct {
craziness: "enormous"
name: "hellocrazyworld"
// …
}
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.
-- in external.qbs file--
import qbs
Group {
files:["file1.cpp", "file2.cpp"]
}
-- in product.qbs file--
import qbs
import "external.qbs" as SourceGroup
Product {
name: "SomeProduct"
SourceGroup {}
}
If opened with qtcreator, files from external.qbs will be visible in a group belonging to 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
}