Documentation/4.3/Developers/Tutorials/BundleModulesIntoExtension

From Slicer Wiki
Jump to: navigation, search
Home < Documentation < 4.3 < Developers < Tutorials < BundleModulesIntoExtension


For the latest Slicer documentation, visit the read-the-docs.


Overview

Extensions are packaged against a specific version of Slicer, to be distributed and available for a revision X of Slicer, extensions have to be build against that same revision of Slicer. Otherwise, an extension will be considered as incompatible.

CMake variables

To create an extension, the following CMake variables should be defined:

CMake variable Description Mandatory
EXTENSION_NAME Name of the extension Check.svg
EXTENSION_HOMEPAGE Url of the web page describing the extension Check.svg
EXTENSION_CATEGORY Extension category Check.svg
EXTENSION_CONTRIBUTORS Extension contributor specified as Firstname1 Lastname1 ([SubOrg1, ]Org1), Firstname2 Lastname2 ([SubOrg2, ]Org2)
EXTENSION_DESCRIPTION One line describing what is the purpose of the extension
EXTENSION_ICONURL Url to an icon (png, size 128x128 pixels)
EXTENSION_SCREENSHOTURLS Space separated list of urls to images
EXTENSION_DEPENDS List of extensions required to build this extension. Specify "NA" if there are no dependency.


List of partially supported CMake variables:

CMake variable Description
EXTENSION_STATUS Give people an idea what to expect from this code

Project layout

The code should be organized as illustrated below:


  MyExtension  <- - - - - - - - - - - - - - - - - - - - - - Top-level folder of the extension project
       |
       |-- CMakeLists.txt
       |
       |-- MyExtension.png
       |
       |-- MyCLIModule
       |        |
       |        |-- CMakeLists.txt
       |        |
       |        |-- MyCLIModule.cxx
       |        |
       |        |-- MyCLIModule.xml
       .        .
       .        .
       |
       |-- MyLoadableModule
                |
                |-- CMakeLists.txt
                |
                |-- qSlicerMyLoadableModuleModule.cxx
                |
                |-- qSlicerMyLoadableModuleModule.h
                .
                .

Top-level CMakeLists.txt

The top-level CMakeLists.txt could be organized as reported below:

cmake_minimum_required(VERSION 2.8.9)

#-----------------------------------------------------------------------------
if(NOT Slicer_SOURCE_DIR)  <- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EXTENSION SPECIFIC
  set(EXTENSION_NAME MyExtension)  <- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EXTENSION SPECIFIC
  set(EXTENSION_HOMEPAGE "http://www.slicer.org/wiki/Documentation/4.1/Extensions/${EXTENSION_NAME}")  <- - - - EXTENSION SPECIFIC
  set(EXTENSION_CATEGORY "Examples")  <- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  EXTENSION SPECIFIC
  set(EXTENSION_CONTRIBUTORS "Jean-Christophe Fillion-Robin (Kitware)")  <- - - - - - - - - - - - - - - - - - - - - - - - - - - EXTENSION SPECIFIC
  set(EXTENSION_DESCRIPTION "This is an example of extension bundling a CLI, a loadable and a scripted module")  <- - - - - - - EXTENSION SPECIFIC
  set(EXTENSION_ICONURL "http://viewvc.slicer.org/viewvc.cgi/Slicer4/trunk/Extensions/Testing/LoadableExtensionTemplate/Resources/Icons/LoadableExtensionTemplate.png?revision=19437&view=co")
endif()  <- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EXTENSION SPECIFIC

#-----------------------------------------------------------------------------
if(NOT Slicer_SOURCE_DIR)
  find_package(Slicer REQUIRED)
  include(${Slicer_USE_FILE})
endif()

#-----------------------------------------------------------------------------
add_subdirectory(MyCLIModule)
add_subdirectory(MyLoadableModule)
[...]

#-----------------------------------------------------------------------------
if(NOT Slicer_SOURCE_DIR)  <- - - - - - - - - - - EXTENSION SPECIFIC
  include(${Slicer_EXTENSION_CPACK})  <- - - - -  EXTENSION SPECIFIC
endif()  <- - - - - - - - - - - - - - - - - - - - EXTENSION SPECIFIC

Possible tweak of Module level CMakeLists.txt

During the development process, it could be useful to be able to build each module against a given slicer build tree without having to build the complete extensions, to do so the CMakeLists.txt of each module could include find_package(Slicer REQUIRED).

For example, the CMakeLists.txt of MyCLIModule module that would be bundled into MyExtension could include the following code:

cmake_minimum_required(VERSION 2.8.9)

#-----------------------------------------------------------------------------
set(MODULE_NAME MyCLIModule) # Do not use 'project()'

#-----------------------------------------------------------------------------
if(NOT Slicer_SOURCE_DIR)
  find_package(Slicer REQUIRED)
  include(${Slicer_USE_FILE})
endif()

[...]


Additional documentation


User FAQ: Extensions

What is an extension ?

Extensions in the Extension manager.

An extension could be seen as a delivery package bundling together one or more Slicer modules. After installing an extension, the associated modules will be presented to the user as built-in ones

The Slicer community maintains a website referred to as the Slicer Extensions Catalog to support finding, downloading and installing of extensions. Access to this website is integral to Slicer and facilitated by the Extensions Manager functionality built into the distributed program.

The Catalog classifies extensions into three levels of compliance:

  1. Category 1: Fully compliant Slicer Extensions: Slicer license, open source, maintained.
  2. Category 2: Open source, contact exists.
  3. Category 3: All other extensions (work in progress, beta, closed source etc).

To publish extensions, developers should consider reading the following pages:

What is the extensions catalog ?

The extensions catalog provides Slicer users with a convenient way to access the extensions previously uploaded on the extensions server:

Why there are no windows 32-bit extensions available ?

  • Win 32 has a very limited amount of memory available to an application.
  • Many registration and segmentation algorithms fail on that platform because they run out of memory, when used with state of large data.
  • Some of these failures are just that, some can crash slicer. Even though the "real" failure is caused by overextending the capabilities of the hardware (in a way the users fault), it appears to the user that Slicer does not work.
  • If you search the archives of slicer-users there are several such complaints until we started to discourage people to use 32 bit.

Discussion: http://massmail.spl.harvard.edu/public-archives/slicer-users/2013/006703.html

Should I install the nightly version to access to last extension updates ?

If the extension developers contributed updates for the current stable release, you don't have to install the nightly version of Slicer. You can simply update the extension. Consider reading How to update an already installed extension ?.

On the other hand, if the extension developers stopped to maintain the version of their extension built against the stable release (so that we can use the latest feature that will be in the next Slicer release), downloading the nightly is the only way to get the latest version of the extension.

How to update an already installed extension?

Assuming updates extensions are available for your version of Slicer, it is currently not possible without uninstalling the extension and re-installing it.

We are currently developing a mechanism allowing to either manually update or automatically suggest update. In the process of finalizing, reviewing and testing, the corresponding feature will be available in Slicer 4.12.

For more details, see [1][2] and [3]

[1] http://na-mic.org/Mantis/view.php?id=2089

[2] https://github.com/mwoehlke-kitware/Slicer/tree/REBASE-2089-update-extensions

[3] http://wiki.slicer.org/wiki/Documentation/Labs/ExtensionsFrameworkRoadmap

How to manually install an extension ?

1) Get revision associated with your install or built Slicer. (Menu -> Help -> About)

2) Download extension matching your Slicer revision. Select operating system, bitness and enter revision on http://slicer.kitware.com/midas3/slicerappstore

3) Extract the archive (zip or tar.gz) in a folder. You should then have a folder like:

/path/to/<slicer_revision>-<os>-<bitness>-<extension_name>-<extension_scm><extension_revision>-YYYY-MM-DD

containing folder like:

lib/Slicer-X.Y/cli-modules
lib/Slicer-X.Y/qt-loadable-modules
lib/Slicer-X.Y/qt-scripted-modules

For more details: Documentation/4.3/Developers/DirectoryStructure

4) In the Module settings (Menu -> Edit -> Settings), add the path ending with lib/Slicer-X.Y/{cli|qt-scripted|qt-loadable}-modules


Developer FAQ: Extensions

Should the name of the source repository match the name of the extension ?

Assuming your extension is named AwesomeFilter, generally, we suggest to name the extension repository either SlicerAwesomeFilter, Slicer-AwesomeFilter, Slicer_AwesomeFilter, SlicerExtension-AwesomeFilter, SlicerExtension_AwesomeFilter.

Doing so will minimize confusion by clearly stating that the code base is associated with Slicer.

What is the Extensions Index ?

Think of the ExtensionsIndex as a repository containing a list of extension description files *.s4ext used by the Slicer extensions build system to build, test, package and upload extensions on the extensions server.

Once uploaded on an extensions server, within Slicer, extensions can be installed using the extensions manager.

The extensions catalog provides Slicer users with a convenient way to access the extensions previously uploaded.

There are multiple branches on the ExtensionsIndex:

  • master: This branch contain description files of extensions that will be built against Slicer nightly.
  • [...]
  • 4.10: This branch contain description files of extensions that will be built against latest Slicer 4.10 available patch release.

The reasoning behind this approach is that since both the Slicer API and ABI associated with Slicer base libraries are changing often, compatibility of the extensions available for download is guaranteed by building extensions against every Slicer revisions.

It means that developer willing to have their extensions available on the different versions of Slicer will have to submit pull requests for each version.

What is an API Key ?

See http://en.wikipedia.org/wiki/Application_programming_interface_key


How to obtain an API key to submit on the extension server ?

In order to upload extensions on the slicer extensions server, it is required to:


  1. Create an account on the extension server: http://slicer.kitware.com by clicking on the Register link in the top right corner

  2. Slicer-midas-extensions-server-registration.png

    This image shows the top portion of http://slicer.kitware.com after it has been expanded by clicking the Register button.

  3. Go to NA-MIC community and click on Join community

  4. Retrieve your API key looking at your account details:

    1. Go to http://slicer.kitware.com. If needed, signin by clicking on Login in the top right corner.
    2. Click on your name in the top right corner.
    3. Click on My account.
    4. Click on API tab.
    5. Copy the API Key associated with Default application.

      1. There is currently a bug preventing api key containing non alpanumeric characters from being used.
        If your Default api key contain for example a /, try to delete the api key and regenerate one that is not containing "/" and is named Default.
        We are working on the issue to update the build system so that it properly escape "/" and also get in touch with Midas team so that api key containing just number and letter are generated.

  5. Slicer-midas-extensions-server-obtaining-api-key.png

Where can I find the extension templates ?

The extensions templates are available in the Slicer source tree: https://github.com/Slicer/Slicer/tree/master/Extensions/Testing/

Using the Wizard, you could easily create a new extension without having to copy, rename and update manually every files.

How to build an extension ?

Assuming that the source code of your extension is located in folder MyExtension, this could be achieved doing:

Makefile Visual Studio
$ mkdir MyExtension-build
$ cd MyExtension-build
$ cmake -DCMAKE_BUILD_TYPE:STRING=Release -DSlicer_DIR:PATH=/path/to/Slicer-Superbuild/Slicer-build ../MyExtension
$ make
  1. Start CMake, select source and build directory
  2. Add Slicer_DIR entry to the cache
  3. Click on Configure, select generator, then click on Generate button.
  4. Open MyExtension.sln, select Release configuration, then menu Project -> Build Solution.

How to package an extension ?

Assuming your extension has been built into folder MyExtension-build, this could be achieved doing:

Makefile Visual Studio
$ make package
  1. Open MyExtension.sln
  2. Select PACKAGES project, then right click and select Build

How to upload an extension ?

Assuming your extension has been built and packaged into folder MyExtension-build, this could be achieved by first re-configuring the project providing your midas credentials and then building the ExperimentalUploadOnly target:

Makefile Visual Studio
$ cmake -DMIDAS_PACKAGE_EMAIL:STRING=<YOUR-MIDAS-LOGIN> -DMIDAS_PACKAGE_API_KEY:STRING=<YOUR-MIDAS-APIKEY> .
$ make ExperimentalUploadOnly
  1. Start CMake, select source and build directory
  2. Add MIDAS_PACKAGE_EMAIL and MIDAS_PACKAGE_API_KEY entries to the cache
  3. Open MyExtension.sln
  4. Select Release configuration
  5. Select ExperimentalUploadOnly project, then right click and select Build

What are the extension specific targets: ExperimentalUpload, ExperimentalUploadOnly, ... ?

Slicer extension build system provides the developer with a set of convenient targets allowing to build and upload extensions.

Target name Description
Experimental Configure, build, test the extension and publish result on CDash.
ExperimentalUpload Equivalent to Experimental target followed by packaging and upload of the extension on the extension server.
ExperimentalUploadOnly Only proceed to the upload of the extension on the extension server.
test or BUILD_TESTS Locally execute the test
package or PACKAGE Locally package the extension

Is --launch flag available for a MacOSX installed Slicer.app ?

On MacOSx, running Slicer with the --help argument does NOT list the usual launcher related options.

$ ./Slicer.app/Contents/MacOS/Slicer --help
Usage
 Slicer [options]
 
 Options
   --, --ignore-rest                     Ignores the rest of the labeled arguments following this flag. (default: false)
   -h, --help                            Display available command line arguments.
   [...]
   --version                             Displays version information and exits.

To provide some background information, when generating the package that will be distributed, an application bundle Slicer.app is created. As explained here, a bundle is a directory with a standardized hierarchical structure that holds executable code and the resources used by that code. It means that since all libraries contained within a bundle are referenced relatively to the location of either the CLI or the Slicer executable, the use of launcher does NOT make sens.

To help fixing-up the libraries, executables and plugins so that they reference each other in a relative way, CMake provides us with the BundleUtilities module.

This module is used in two situations:

  1. Fixup of Slicer application itself. See SlicerCPack.cmake#L36-68 and SlicerCPackBundleFixup.cmake.in
  2. Fixup of an extension package. See SlicerExtensionCPack.cmake#L126-143 and SlicerExtensionCPackBundleFixup.cmake.in


What is the difference between Documentation/Nightly/Modules and Documentation/Nightly/Extensions ?

As suggested by the namespace names:

  • All module documentation pages should be located under Documentation/Nightly/Modules
  • All extension documentation pages should be located under Documentation/Nightly/Extensions


For example, if an an extension named DoSomethingGreat bundles three modules ModuleA, ModuleB and ModuleC. The following pages should be created:

  • Documentation/Nightly/Extensions/DoSomethingGreat
  • Documentation/Nightly/Modules/ModuleA
  • Documentation/Nightly/Modules/ModuleB
  • Documentation/Nightly/Modules/ModuleC


In case your extension bundles only one module, the extension name is expected to match the module name. For example, if your extension is named DoSomethingAwesome, the associated module is expected to be named DoSomethingAwesome. The following pages will then be created:

  • Documentation/Nightly/Extensions/DoSomethingAwesome
  • Documentation/Nightly/Modules/DoSomethingAwesome

where page Extensions/DoSomethingAwesome redirect to page Modules/DoSomethingAwesome.


To setup a redirection, simply add the following text to page Extensions/DoSomethingAwesome:

#REDIRECT [[Documentation/Nightly/Modules/DoSomethingAwesome]]

For an example, see here

More details about redirection are available here: http://www.mediawiki.org/wiki/Help:Redirects


Which URL should be associated with EXTENSION_HOMEPAGE metadata ?

Extensions available through the Slicer Extensions Catalog are expected to have a page created under the Nightly documentation namespace. The corresponding URL should be associated with the EXTENSION_HOMEPAGE metadata.

For example:

  • set(EXTENSION_HOMEPAGE "http://slicer.org/wiki/Documentation/Nightly/Extensions/DoSomethingGreat")
  • set(EXTENSION_HOMEPAGE "http://slicer.org/wiki/Documentation/Nightly/Extensions/DoSomethingAwesome")

Note that this also apply for extension bundling only one module. Indeed, in this case the page will redirect to the appropriate module page. For example: http://www.slicer.org/wiki/Documentation/Nightly/Extensions/SkullStripper

How to rename an extension to add new features ?

If you created an extension to perform Task1, but later on, your module is getting more generic and you add some other tasks, the name of your extension might change. In order to rename, your extension, you should:

  • Remove your old extension from the ExtensionsIndex
  • Then, submit your extension again (including new features) with a new name
  • Make also sure to add redirection from the "deprecated" module documentation to the "new" pages. On the Slicer wiki, this could be using the #REDIRECT instruction.