Building component packages

Component packages can be built either on the command line or graphically in the Builder. This document describes how to use the va-pkg command-line tool to build packages.

The packaging tool is in the bin directory of the VisionAppster installation. If it is in your PATH, this command will give you basic usage instructions:

va-pkg

If you installed the Flatpak version on Linux, type this first:

alias va-pkg="flatpak run --command=va-pkg com.visionappster.Builder"

Adding --help after a sub-command name will show you help on that sub-command.

Generally, the process of creating a component package has three phases:

  1. Create a directory structure with all the files that will go into the package.
  2. Create a manifest file, component.json, at the root.
  3. Zip the directory.

Native tool plugins

Native tool plugins are created using the C tool API. An OpenCV-based C++ project template can be found here. If you need the plugin only internally, this is all you need on any platform.

If your intent is to publicly sell the plugin through VisionAppster Store, things become a bit more challenging. To prevent fragmentation of the platform, we require that all publicly distributed native extensions have been compiled for all the supported target platforms. Privately sold extensions don't have this requirement. Furthermore, code that runs on VisionAppster Cloud as an API only needs to support Linux x86_64.

To build compliant native plugins, use our cross-compilation tools. They can also be used for example if you work on Windows and want your code to run in the cloud.

As a result of the build process, you'll get one or more .toolplugin files, one for each supported architecture. These files are just shared libraries with a special extension.

The convention is to place native tool plugins into directories that specify the target architecture. So, at the minimum, the directory structure that goes into a tool plugin package is like this:

mycomponent/
mycomponent/linux-x86_64/
mycomponent/linux-x86_64/mycooltools.toolplugin

Here, mycomponent/ is the root directory that will hold the manifest file, component.json. The file doesn't exist yet, but any update command will automatically create it. Since we followed the naming conventions, creating a manifest file is straightforward. Give this command in the parent directory of mycomponent/:

va-pkg update \
  --component-id com.example.tools.cool \
  --version 1.0.0 \
  --scan mycomponent

Here, com.example.tools.cool is the ID of your component. The --scan flag instructs va-pkg to scan the whole directory hierarchy and add all found files to the manifest file. Now you have what makes up a working package at a minimum:

mycomponent/
mycomponent/component.json
mycomponent/linux-x86_64/
mycomponent/linux-x86_64/mycooltools.toolplugin

To build the package:

va-pkg build mycomponent

This will create com.example.tools.cool-1.0.0.vapkg in the current directory. You can inspect the contents of the package with unzip:

unzip -l com.example.tools.cool-1.0.0.vapkg

The output should list these files:

com.example.tools.cool/1/linux-x86_64/mycooltools.toolplugin
com.example.tools.cool/1/component.json

Tool files

Tool files contain processing graphs created in the Builder. They contain no native code and are thus executable on all supported platforms, provided that the native extensions used by the graph have been installed.

The processing graph and its parameters may be valuable information you want to protect. While the .tool file format isn't designed to be human-readable, it isn't too hard to figure out its contents. Obviously, the Builder can easily open them for introspection.

To protect your IPR, va-pkg makes it possible to encrypt .tool files. An encrypted processing graph can be loaded and executed by the VisionAppster Engine only if it comes from an installed component that has a valid digital signature, and the full component ID of that component matches the ID assigned to the .tool file. If an encrypted tool file is loaded in the Builder, it will appear just like a native tool that cannot be opened.

Since encrypted files require a valid signature, they can only be used if the package has been validated and signed by VisionAppster Store. You must register the component ID using your seller account and use the full component ID to encrypt files.

Let's assume you have created a processing graph, made it a compound and saved it as a .tool file. To include this file in a component package you just need to copy the file to the package directory. The contents of the directory will look like this:

mycomponent/
mycomponent/component.json
mycomponent/MyComplexTool.tool
mycomponent/linux-x86_64/
mycomponent/linux-x86_64/mycooltools.toolplugin

To encrypt the file, give this command in the root directory of the package (mycomponent/):

va-pkg tool encrypt \
  --full-component-id com.example.tools.cool/1 \
  MyComplexTool.tool

This will encrypt MyComplexTool.tool in a way that makes it unloadable from any component other than one with a full component ID of com.example.tools.cool/1 and a valid signature. The encrypted tool will be saved to MyComplexTool.toolc.

Alternatively, you can create a new package and make the package containing the native tool plugin a dependency (with va-pkg update --depends). Here, we'll incorporate everything into a single component. Add the encrypted file to the manifest:

va-pkg update files +MyComplexTool.toolc .

Alternatively, va-pkg update --scan . can be used.

Now, if you build the component package again with va-pkg build, it will contain MyComplexTool.toolc. When installed, this tool will appear among other tools in the Builder as "My Complex Tool".

Apps

When you save a project in the Builder, the Builder creates an app that runs a processing graph. The app is stored in the analysisapp/ directory under the project directory. Since the app is built in the Builder, the natural way to create a component package out of it is to use the Builder.

It is usually a good idea to build required tools into a separate component and add the full component IDs of required tool plugins as dependencies to the app component. You can do this in the Builder's graphical interface.

Alternatively, you can create a self-contained app component by copying the app's files from analysisapp/ to the root directory of your tool plugin component:

mycomponent/
mycomponent/component.json
mycomponent/main.qml
mycomponent/appconfig.json
mycomponent/engine.tool
mycomponent/MyComplexTool.tool
mycomponent/linux-x86_64/
mycomponent/linux-x86_64/mycooltools.toolplugin

The component ID of such a package would need to be changed. This requires a change in the native C code that implements the tool plugin. If you want to encrypt the .tool files, the new ID must be given there as well:

va-pkg tool encrypt \
  --full-component-id com.example.apps.cool/1 engine.tool
va-pkg tool encrypt \
  --full-component-id com.example.apps.cool/1 MyComplexTool.tool

The manifest must also be updated:

va-pkg update --component-id com.example.apps.cool --scan .

Finally, the package can be built:

cd ..
va-pkg build mycomponent

This will create com.example.apps.cool-1.0.0.vapkg that contains not only the app but also a native tool plugin and a tool file.

Store packages

If you want to distribute your component through VisionAppster Store or run an app in VisionAppster Cloud, you must register the component ID using your seller account. During the registration process, your component will be assigned a UUID and a name. When you build a component for the Store, these need to be stored in the manifest:

va-pkg update \
  --uuid 9ab4862d-bfd8-4d8e-a044-505b54d7f55f \
  --name "My cool component" mycomponent
va-pkg build mycomponent

Signing

If the package contains encrypted tool files or copy-protected native tool plugins, you'll be unable to use them unless the package has a valid signature. Packages will be signed by the cloud service once they have gone through validation. But this may take time and you usually want to test the package yourself before uploading it to validation. Therefore, VisionAppster Cloud provides an API for signing packages. The URL of the API is

https://could.visionappster.com/api/1/signatures/sign

The package to be signed is uploaded using HTTP POST:

curl --data-binary "@com.example.apps.cool-1.0.0.vapkg" \
  --header "Content-Type: application/vnd.va-pkg" \
  --header "Authorization: Bearer API-TOKEN" \
  --header "Buyer-ID: BUYER-ID-1,BUYER-ID-2..." \
  -X POST \
  https://could.visionappster.com/api/1/signatures/sign \
  > com.example.apps.cool-1.0.0-signed.vapkg

The Content-Type header tells the server how to handle the body of the message.

The Authorization header must contain an API token that can be generated for a seller account in the cloud service. The server inspects the token and verifies that it is valid and belongs to a seller account that owns the uploaded package.

The Buyer-ID header contains a comma-separated list of UUIDs. Each identifies a buyer account to which a temporary license is generated. The license allows 24 hours of usage for the single uploaded component.

The server performs basic integrity checks to ensure that the format of the package is OK, generates a signature file for component.json (component.json.crt) and sends the signed package back in the response body. On error, you'll get an appropriate HTTP error code.

Retrieving licenses

The signing API lets you to give a short-term license to any buyer account. If you have installed any packages from the Store using the buyer account, the new license should available automatically. It is also possible to retrieve the licenses manually. The URL of the license API is

https://cloud.visionappster.com/api/1/users/BUYER-ID/licenses.vapkg

To retrieve the license file, give the following command:

curl --header "Authorization: Bearer API-TOKEN" \
  https://could.visionappster.com/api/1/users/BUYER-ID/licenses.vapkg \
  > licenses.vapkg

Here, BUYER-ID is the UUID of your buyer account, which was also used in the signing API call. API-TOKEN is an authorization key you can set in your buyer account.

The server returns your licenses as a component package that can be installed just like any package.