Commit b5b6a46b authored by Eike Ziller's avatar Eike Ziller
Browse files

ExtensionSystem: Use Qt 5 plugin metadata instead of .pluginspec files



Change-Id: I2b2c704260c613985a4bda179658ec1f8879e70f
Reviewed-by: default avatarChristian Kandeler <christian.kandeler@digia.com>
Reviewed-by: default avatarChristian Stenger <christian.stenger@digia.com>
Reviewed-by: default avatarDaniel Teske <daniel.teske@digia.com>
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent 8dc9d67e
......@@ -40,7 +40,6 @@ Thumbs.db
*.creator.user*
*.qbs.user*
*.qmlproject.user*
*.pluginspec
*.json
/src/app/Info.plist
app_version.h
......
......@@ -46,7 +46,7 @@
\list
\li \l{Getting and Building Qt Creator}
\li \l{Creating Your First Plugin}
\li \l{Plugin Specifications}
\li \l{Plugin Meta Data}
\li \l{Plugin Life Cycle}
\endlist
......
{
//! [1]
\"Name\" : \"Example\",
\"Version\" : \"0.0.1\",
\"CompatVersion\" : \"0.0.1\",
//! [1]
//! [2]
\"Vendor\" : \"My Company\",
\"Copyright\" : \"(C) My Company\",
\"License\" : \"BSD\",
\"Category\" : \"Examples\",
\"Description\" : \"Minimal plugin example.\",
\"Url\" : \"http://www.mycompany.com\",
//! [2]
//! [3]
$$dependencyList
//! [3]
}
//! [1]
<plugin name=\"Example\" version=\"0.0.1\" compatVersion=\"0.0.1\">
//! [1]
//! [2]
<vendor>MyCompany</vendor>
<copyright>(C) MyCompany</copyright>
<license>BSD</license>
<description>Minimal plugin example</description>
<url>http://www.mycompany.com</url>
//! [2]
//! [3]
$$dependencyList
//! [3]
</plugin>
......@@ -141,9 +141,10 @@
\li File
\li Role
\row
\li \c{Example.pluginspec.in}
\li Template plugin specification. QMake creates a \c{Example.pluginspec}
from this file, which is read by \QC to find out about the plugin.
\li \c{Example.json.in}
\li Plugin meta data template. QMake creates an \c{Example.json}
from this file, which is compiled into the plugin as meta data.
The meta data is read by \QC to find out about the plugin.
\row
\li \c{example.pro}
\li Project file, used by QMake to generate a Makefile that then is used to
......@@ -222,32 +223,32 @@
For more information about qmake, and writing .pro files in general,
see the \l{http://qt-project.org/doc/qt-4.8/qmake-manual.html}{qmake Manual}.
\section1 Plugin Specification
\section1 Plugin Meta Data Template
The .pluginspec file is an XML file that contains information that is needed by
The .json file is a JSON file that contains information that is needed by
the plugin manager to find your plugin and resolve its dependencies before actually
loading your plugin's library file. We will only have a short look at it here.
For more information, see \l{Plugin Specifications}.
For more information, see \l{Plugin Meta Data}.
The wizard doesn't actually create a .pluginspec file directly, but instead a
.pluginspec.in file. qmake uses this to generate the actual plugin specification
The wizard doesn't actually create a .json file directly, but instead a
.json.in file. qmake uses this to generate the actual plugin .json meta data
file, replacing variables like \c{QTCREATOR_VERSION} with their actual values.
Therefore you need to escape all backslashes and quotes in the .pluginspec.in file
Therefore you need to escape all backslashes and quotes in the .json.in file
(i.e. you need to write \c{\\} to get a backslash and \c{\"} to get a quote
in the generated plugin specification).
in the generated plugin JSON meta data).
\snippet exampleplugin/Example.pluginspec.in 1
\snippet exampleplugin/Example.json.in 1
The main tag of the plugin specification that is created by the wizard
defines the name of your plugin, its version, and with what version of this plugin
The first items in the meta data that is created by the wizard
define the name of your plugin, its version, and with what version of this plugin
the current version is binary compatible with.
\snippet exampleplugin/Example.pluginspec.in 2
\snippet exampleplugin/Example.json.in 2
After the main tag you'll find the information about the plugin
After that you'll find the information about the plugin
that you gave in the project wizard.
\snippet exampleplugin/Example.pluginspec.in 3
\snippet exampleplugin/Example.json.in 3
The \c{$$dependencyList} variable is automatically replaced by the dependency information
in \c{QTC_PLUGIN_DEPENDS} and \c{QTC_PLUGIN_RECOMMENDS} from your plugin's .pro file.
......@@ -272,6 +273,9 @@
All \QC plugins must be derived from \l{ExtensionSystem::IPlugin} and
are QObjects. The \c{Q_PLUGIN_METADATA} macro is necessary to create a valid Qt plugin.
The \c IID given in the macro must be \c{org.qt-project.Qt.QtCreatorPlugin}, to identify it
as a \QC plugin, and \c FILE must point to the plugin's meta data file as described
in \l{Plugin Meta Data}.
\snippet exampleplugin/exampleplugin.h plugin functions
......
......@@ -24,12 +24,18 @@
manager takes when you start or shut down \QC. This section describes
the process and the state that plugins go through in detail.
You can get more information about what happens when you start \QC by running it with the
environment variable \c QT_LOGGING_RULES set to \c {qtc.extensionsystem*=true} which enables
logging of plugin-related debug output.
When you start \QC, the plugin manager does the following:
\list 1
\li Looks in its search paths for
all .pluginspec files, and reads them. This is the first point where
loading a plugin can fail in the worst case of a malformed plugin spec.
all dynamic libraries, and reads their meta data. All libraries without meta data
and all libraries without the \c{org.qt-project.Qt.QtCreatorPlugin} IID are ignored.
This is the first point where loading a plugin can fail in the worst case of malformed
meta data.
\li Creates an instance of the \l{ExtensionSystem::PluginSpec} class for
each plugin. This class is a container for
......
......@@ -17,113 +17,115 @@
**************************************************************************/
/*!
\page plugin-specifications.html
\title Plugin Specifications
\page plugin-meta-data.html
\title Plugin Meta Data
The specification of a plugin is an XML file that contains all
The meta data file of a plugin is a JSON file that contains all
information that is necessary for loading the plugin's library,
determining whether plugins are to be loaded and in which order (depending
on e.g. dependencies). In addition, it contains textual descriptions of
who created the plugin, what it is for, and where to find more information about it.
The file must be located in (a subdir of) one of the plugin manager's
plugin search paths, and must have the \c .pluginspec extension.
The file must be located in one of the include search paths when compiling the plugin,
and must have the \c .json extension. The JSON file is compiled into the plugin as meta data,
which then is read by \QC when loading plugins.
\section2 Main Tag
\section2 Main Keys
The root tag is \c plugin. It has the mandatory attributes \c name
and \c version, and the optional attributes \c compatVersion, \c experimental,
\c disabledByDefault and \c required.
The main keys that are used to identify your your plugin and define default loading behavior,
consist of the mandatory keys \c Name and \c Version, and the optional keys \c CompatVersion,
\c Experimental, \c DisabledByDefault, \c Required and \c Platform.
\table
\header
\li Tag
\li Key
\li Value Type
\li Meaning
\row
\li plugin
\li Root element in a plugin's XML file.
\endtable
\table
\header
\li Attribute
\li Meaning
\row
\li name
\li Name
\li String
\li This is used as an identifier for the plugin and can e.g.
be referenced in other plugin's dependencies. It is
also used to construct the name of the plugin library
as \c{lib[name].[dll|.so|.dylib]}. (Depending on platform.
If you use the same string as the \c TARGET in your plugin's
.pro-file, you are fine.)
be referenced in other plugin's dependencies.
\row
\li version
\li Version
\li String
\li Version string in the form \c{x.y.z_n}, used for identifying
the plugin. Also see \l{A Note on Plugin Versions}.
\row
\li compatVersion
\li CompatVersion
\li String
\li Optional. If not given, it is implicitly
set to the same value as \c version. The compatibility version
set to the same value as \c Version. The compatibility version
states which version of this plugin the current version is
binary backward compatible with and is used to resolve dependencies
on this plugin. I.e. a \c version of \c{2.1.1} and a
\c compatVersion of \c{2.0.0} means that this version \c{2.1.1} of the plugin
on this plugin. I.e. a \c Version of \c{2.1.1} and a
\c CompatVersion of \c{2.0.0} means that this version \c{2.1.1} of the plugin
is binary backward compatible with all versions of the plugin down to \c{2.0.0}
(inclusive).
\row
\li experimental
\li Optional. Can be \c true or \c false, defaults to \c false.
\li Experimental
\li Boolean
\li Optional. Defaults to \c false.
Experimental plugins are not loaded by default but must be explicitly
enabled by the user. This attribute should be enabled for new plugins which have the
potential to negatively affect the user experience.
\row
\li disabledByDefault
\li Optional. Can be \c true or \c false, defaults to \c false.
\li DisabledByDefault
\li Boolean
\li Optional. Defaults to \c false.
If set, the respective plugin is not loaded by default but must be explicitly
enabled by the user. This should be done for plugins which are not expected
to be used by so many people as to justify the additional resource consumption.
\row
\li required
\li Optional. Can be \c true or \c false, defaults to \c false.
\li Required
\li Boolean
\li Optional. Defaults to \c false.
Is used as a hint for the \gui{About Plugins...} dialog, that the user may not
manually disable this plugin. Only used for the Core plugin.
\row
\li Platform
\li String
\li Optional. A regular expression that matches the names of the platforms the plugin
works on. Omitting the tag implies that the plugin is loaded on all platforms.
\endtable
\section2 Plugin-describing Tags
\section2 Plugin-describing Keys
These are direct children of the \c plugin tag, and are solely used
for more detailed (user centric) description of the plugin. All of these
These are solely used for more detailed (user centric) description of the plugin. All of these
are optional.
\table
\header
\li Tag
\li Key
\li Value Type
\li Meaning
\row
\li category
\li Category
\li String
\li Defaults to \c Utilities. Is used to put related plugins
under the same tree node in the plugin overview \gui{About Plugins...}.
\row
\li vendor
\li Vendor
\li String
\li String that describes the plugin creator/vendor,
like \c{MyCompany}.
\row
\li copyright
\li Copyright
\li String
\li A short copyright notice, like \c{(C) 2007-2008 MyCompany}.
\row
\li platform
\li A regular expression that matches the names of the platforms the plugin works on.
Omitting the tag implies that the plugin is loaded on all platforms.
\row
\li license
\li License
\li String or array of strings
\li Possibly multi-line license information about the plugin.
Should still be kept relatively short, since the UI is not
designed for long texts.
\row
\li description
\li Description
\li String or array of strings
\li Possibly multi-line description of what the plugin is supposed
to provide.
Should still be kept relatively short, since the UI is not
designed for long texts.
\row
\li url
\li Url
\li String
\li Link to further information about the plugin, like
\c{http://www.mycompany-online.com/products/greatplugin}.
\endtable
......@@ -131,70 +133,84 @@
\section2 Dependencies
A plugin can have dependencies on other plugins. These are
specified in the plugin description, to ensure that
specified in the plugin meta data, to ensure that
these other plugins are loaded before this plugin.
The XML element that describes a single dependency is the \c dependency tag,
with required attributes \c name and \c version. All \c dependency tags
must be enclosed in a single \c dependencyList tag, which is an optional
child of the \c plugin tag.
Dependencies are declared with the key \c Dependency, which contains an array of JSON objects
with required keys \c Name and \c Version, and optional key \c Type.
The following formulas illustrate how the dependency information is matched.
In the formulas the name of the required plugin (as defined in the attributes
of the \c dependency tag) is denoted as \c dependencyName
and the required version of the plugin is denoted as \c dependencyVersion.
A plugin with given \c name, \c version and \c compatVersion
(as defined in the attributes of the plugin's \c plugin tag) matches
In the formulas the name of the required plugin (as defined in the \c Name of the dependency
object) is denoted as \c DependencyName
and the required version of the plugin is denoted as \c DependencyVersion.
A plugin with given \c Name, \c Version and \c CompatVersion
as defined in the plugin meta data matches
the dependency if
\list
\li its \c name matches \c dependencyName, and
\li \c {compatVersion <= dependencyVersion <= version}.
\li its \c Name matches \c DependencyName, and
\li \c {CompatVersion <= DependencyVersion <= Version}.
\endlist
For example a dependency
\code
<dependency name="SomeOtherPlugin" version="2.3.0_2"/>
{
"Name" : "SomeOtherPlugin",
"Version" : "2.3.0_2"
}
\endcode
would be matched by a plugin with
\code
<plugin name="SomeOtherPlugin" version="3.1.0" compatVersion="2.2.0">
{
"Name" : "SomeOtherPlugin",
"Version" : "3.1.0",
"CompatVersion" : "2.2.0",
...
}
\endcode
since the name matches, and the version \c{2.3.0_2} given in the dependency tag
lies in the range of \c{2.2.0} and \c{3.1.0}.
\table
\header
\li Tag
\li Key
\li Value Type
\li Meaning
\row
\li dependency
\li Describes a dependency on another plugin.
\li Dependencies
\li Array of dependency objects
\li Describes the dependencies on other plugins.
\endtable
A dependency object is a JSON object with the following keys:
\table
\header
\li Attribute
\li Key
\li Value Type
\li Meaning
\row
\li name
\li Name
\li String
\li The name of the plugin, on which this plugin relies.
\row
\li version
\li Version
\li String
\li The version to which the plugin must be compatible to
fill the dependency, in the form \c{x.y.z_n}.
Can be empty if the version does not matter.
\row
\li type
\li Optional. Value \c required or \c optional. Defines if the dependency is
a hard requirement or optional. Defaults to \c{required}.
\li Type
\li String
\li Optional. Value \c Required or \c Optional. Defines if the dependency is
a hard requirement or optional. Defaults to \c{Required}.
\endtable
\section3 Optional Dependencies
A plugin can specify that a dependency on another plugin is optional, by adding the
\c {type="optional"} attribute to the \c dependency tag:
A plugin can specify that a dependency on another plugin is optional, by adding
\c {"Type" : "Optional"} to the dependency object:
\list
\li If the dependency can be resolved, the plugin and
its dependency are loaded and initialized as for \c required dependencies.
its dependency are loaded and initialized as for \c Required dependencies.
\li If the dependency cannot be resolved, the plugin is loaded and initialized
as if the dependency was not declared at all.
\endlist
......@@ -218,61 +234,77 @@
it passes them on to the plugin's
\l{ExtensionSystem::IPlugin::initialize()}{initialize()} function.
All command line argument definitions are enclosed by a single \c argumentList
tag. The individual command line arguments are defined by the \c argument tag,
with required attribute \c name and an optional attribute \c parameter if the
command line argument takes an additional parameter. The text that is enclosed
in the \c argument tag is used as a (one-line) description in the command line
argument help.
Command line arguments are defined through the key \c Arguments, which contains an array
of argument objects. Each individual argument object has the required key \c Name, and
optional keys \c Parameter and \c Description.
\table
\header
\li Tag
\li Key
\li Value Type
\li Meaning
\row
\li argument
\li Describes a command line argument that the plugin wants to handle.
\li Arguments
\li Array of argument objects
\li Describes the command line arguments that the plugin wants to handle.
\endtable
An argument object is a JSON object with the following keys:
\table
\header
\li Attribute
\li Key
\li Value Type
\li Meaning
\row
\li name
\li Name
\li String
\li The command line argument itself, including the \c - prefix, e.g.
\c{-my-parameter}.
\row
\li parameter
\li Parameter
\li String
\li Optional. If this is given, the command line argument expects an
additional parameter, e.g. \c{-my-parameter somevalue}. The
value of this attribute is used as a very short description of the
parameter for the user.
\row
\li Description
\li String
\li Optional. A (one-line) description of the argument for the command line argument help.
\endtable
\section2 Example \c Test.pluginspec
\section2 Example \c Test.json
\code
<plugin name="Test" version="1.0.1" compatVersion="1.0.0">
<vendor>MyCompany</vendor>
<copyright>(C) 2007 MyCompany</copyright>
<license>
This is a default license bla
blubbblubb
end of terms
</license>
<description>
This plugin is just a test.
it demonstrates the great use of the plugin spec.
</description>
<url>http://www.mycompany-online.com/products/greatplugin</url>
<dependencyList>
<dependency name="SomeOtherPlugin" version="2.3.0_2"/>
<dependency name="EvenOther" version="1.0.0"/>
</dependencyList>
<argumentList>
<argument name="-variant" parameter="fancy|boring">Brings up the fancy or boring user interface</argument>
</argumentList>
</plugin>
{
"Name" : "Test",
"Version" : "1.0.1",
"CompatVersion" : "1.0.0",
"Vendor" : "My Company",
"Copyright" : "(C) 2007 MyCompany",
"License" : [
"This is a default license bla",
"blubbblubb",
"end of terms"
],
"Category" : "My Company Additions",
"Description" : [
"This plugin is just a test.",
"It demonstrates the great use of the plugin meta data."
],
"Url" : "http://www.mycompany-online.com/products/greatplugin",
"Arguments" : [
{
"Name" : "-variant",
"Parameter" : "fancy|boring",
"Description" : "Brings up the fancy or boring user interface"
}
],
"Dependencies" : [
{ "Name" : "SomeOtherPlugin", "Version" : "2.3.0_2" },
{ "Name" : "EvenOther", "Version" : "1.0.0" }
]
}
\endcode
\section2 A Note on Plugin Versions
......
......@@ -54,7 +54,7 @@ DEV_HELP_DEP_FILES = \
$$PWD/api/creating-plugins.qdoc \
$$PWD/api/getting-and-building.qdoc \
$$PWD/api/first-plugin.qdoc \
$$PWD/api/plugin-specifications.qdoc \
$$PWD/api/plugin-metadata.qdoc \
$$PWD/api/plugin-lifecycle.qdoc \
$$PWD/api/pluginmanager.qdoc \
$$PWD/api/qtcreator-dev$${COMPAT}.qdocconf
......
......@@ -7,7 +7,7 @@ QtcProduct {
type: ["dynamiclibrary", "pluginSpec"]
installDir: project.ide_plugin_path
property var pluginspecreplacements
property var pluginJsonReplacements
property var pluginRecommends: []
property string minimumQtVersion: "5.3.1"
......@@ -17,7 +17,7 @@ QtcProduct {
destinationDirectory: project.ide_plugin_path
Depends { name: "ExtensionSystem" }
Depends { name: "pluginspec" }
Depends { name: "pluginjson" }
Depends {
condition: project.testsEnabled
name: "Qt.test"
......@@ -39,9 +39,9 @@ QtcProduct {
cpp.includePaths: [pluginIncludeBase]
Group {
name: "PluginSpec"
files: [ product.name + ".pluginspec.in" ]
fileTags: ["pluginSpecIn"]
name: "PluginMetaData"
files: [ product.name + ".json.in" ]
fileTags: ["pluginJsonIn"]
}
Group {
......
......@@ -5,27 +5,31 @@ import qbs.FileInfo
Module {
Depends { id: qtcore; name: "Qt.core" }
additionalProductTypes: qtcore.versionMajor < 5 ? ["pluginSpec"] : ["qt_plugin_metadata"]
additionalProductTypes: ["qt_plugin_metadata"]
Rule {
inputs: ["pluginSpecIn"]
inputs: ["pluginJsonIn"]
Artifact {
fileTags: ["pluginSpec"]
filePath: input.fileName.replace(/\.[^\.]*$/,'')
fileTags: ["qt_plugin_metadata"]
filePath: {
var destdir = FileInfo.joinPaths(product.moduleProperty("Qt.core",
"generatedFilesDir"), input.fileName);
return destdir.replace(/\.[^\.]*$/,'')
}
}
prepare: {
var cmd = new JavaScriptCommand();
cmd.description = "prepare " + FileInfo.fileName(output.filePath);
cmd.highlight = "codegen";
cmd.pluginspecreplacements = product.pluginspecreplacements;
cmd.pluginJsonReplacements = product.pluginJsonReplacements;
cmd.plugin_depends = [];
var deps = product.dependencies;
for (var d in deps) {
var depdeps = deps[d].dependencies;
for (var dd in depdeps) {
if (depdeps[dd].name == 'pluginspec') {
if (depdeps[dd].name == 'pluginjson') {
cmd.plugin_depends.push(deps[d].name);
break;
}
......@@ -35,7 +39,7 @@ Module {
cmd.sourceCode = function() {
var i;
var vars = pluginspecreplacements || {};
var vars = pluginJsonReplacements || {};
var inf = new TextFile(input.filePath);
var all = inf.readAll();
// replace quoted quotes
......@@ -46,15 +50,15 @@ Module {
vars['IDE_VERSION_MAJOR'] = project.ide_version_major;
vars['IDE_VERSION_MINOR'] = project.ide_version_minor;
vars['IDE_VERSION_RELEASE'] = project.ide_version_release;
var deplist = ["<dependencyList>"];
var deplist = [];
for (i in plugin_depends) {
deplist.push(" <dependency name=\"" + plugin_depends[i] + "\" version=\"" + project.qtcreator_version + "\"/>");
deplist.push(" { \"Name\" : \"" + plugin_depends[i] + "\", \"Version\" : \"" + project.qtcreator_version + "\" }");
}
for (i in plugin_recommends) {
deplist.push(" <dependency name=\"" + plugin_recommends[i] + "\" version=\"" + project.qtcreator_version + "\" type=\"optional\"/>");
deplist.push(" { \"Name\" : \"" + plugin_recommends[i] + "\", \"Version\" : \"" + project.qtcreator_version + "\", \"Type\" : \"optional\" }");
}
deplist.push(" </dependencyList>");