# Installing extensions in binary distribution of Slicer

**URL:** <https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511>\
**Category:** Support\
**Tags:** extensions-manager\
**Created:** [July 10, 2019, 10:59pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511 "2019-07-10T22:59:39Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![tbillah](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tbillah/32/4139_2.png) [@tbillah](https://discourse.slicer.org/u/tbillah)\
**Post date:** [July 10, 2019, 10:59pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/1 "2019-07-10T22:59:39Z")

</div>

I need to install a few extensions like [SlicerDMRI](http://dmri.slicer.org/) and make it available for everyone at my office.

On Partner’s cluster environment, compiling Slicer from source code with desirable `.s4ext` files, isn’t the best option.

So, I have to resort to `ExtensionManager` on the Slicer GUI. I installed my desired extensions. The modules are discoverable when I launch Slicer. However, they are not discoverable to other users automatically. Interestingly, when I use a different workstation, they are not discovered either.

I have tried `./Slicer --additional-module-paths path1 path2 ...`, but I ran into errors that stem from incomplete `PYTHONPATH` and `LD_LIBRARY_PATH`.

The question is, what is the most manageable way to install extensions and make it available for all users using that Slicer?

---

<div class="post-metadata">

**Author:** ![jcfr](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jcfr/32/17825_2.png) [@jcfr](https://discourse.slicer.org/u/jcfr)\
**Post date:** [July 11, 2019, 7:02am UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/2 "2019-07-11T07:02:10Z")

</div>

~~Assuming the user where Slicer and the extensions are installed is called `slicer`,~~ the idea is to create a script called `SlicerWithExtensions.sh` along side the Slicer launcher in your shared installation.

The script only need to be updated with the name of the user under which Slicer is installed on the cluster:

```bash
#!/bin/bash -e

# This is the username associated with the Slicer installation to share between users.
slicer_user=jcfr # TODO: Update this line

script_dir=$(cd $(dirname $0) || exit 1; pwd)
script_name=$(basename $0)

# launcher and launcher settings
launcher=${script_dir}/Slicer
launcher_settings=${script_dir}/bin/SlicerLauncherSettings.ini
echo "Launcher settings ........: ${launcher_settings}"

# sanity checks
if [! -f ${launcher}]; then
  echo "${script_name} is expected to exist along side the Slicer launcher: ${launcher} not found"
  exit 1
fi
if [! -f ${launcher_settings}]; then
  echo "${script_name} is expected to exist along side the Slicer launcher: ${launcher_settings} not found"
  exit 1
fi

# extract revision
revision=$(cat ${launcher_settings} | grep revision= | cut -d= -f2)
echo "Revision .................: ${revision}"

# revision user settings
slicer_revision_user_settings=/home/${slicer_user}/.config/NA-MIC/Slicer-${revision}.ini
echo "Revision user settings ...: ${launcher_settings}"

# sanity check
if [! -f ${slicer_revision_user_settings}]; then
  echo "Slicer revision user settings not found: ${slicer_revision_user_settings}"
  exit 1
fi

# extract additional module paths
# TODO Handle module path with spaces
additional_module_paths=$(cat ${slicer_revision_user_settings} | grep AdditionalPaths= | cut -d= -f2 | tr -d ",")
echo "Additional module paths ..: ${additional_module_paths}"

${launcher} --launcher-additional-settings ${slicer_revision_user_settings} --additional-module-paths ${additional_module_paths} "$@"

```

### more details

Generally speaking, extensions are installed in the Slicer setting directory specific to the user and all information are added to a ini file. For example, the ini file associated Slicer 4.10.1 on linux is `~/.config/NA-MIC/Slicer-27931.ini`.

After installing an extension, you can see settings groups like `[LibraryPaths]`, `[PYTHONPATH]`, `[Paths]` and also `[Modules]` with the key `AdditionalPaths`.

To automatically set the environment before starting the real Slicer application, the Slicer launcher is able to infer the path to the user Slicer revision specific file `~/.config/NA-MIC/Slicer-27931.ini` given information found in the launcher settings.

Here is a snippet of the launcher settings associated with Slicer 4.10.1 (e.g. `/path/to/Slicer-4.10.1-linux-amd64/bin/SlicerLauncherSettings.ini`)

```auto
[...]

[Application]
path=<APPLAUNCHER_DIR>/bin/SlicerApp-real
arguments=
name=Slicer
revision=27931
organizationDomain=www.na-mic.org
organizationName=NA-MIC

[...]

```

Within the `[Application]` group, we can see the key `name`, `revision` and `organizationName`. These information are sufficient to retrieve the revision specific settings file and compose the environment needed to load the additional modules associated with the `AdditionalPaths` key.

---

<div class="post-metadata">

**Author:** ![tbillah](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tbillah/32/4139_2.png) [@tbillah](https://discourse.slicer.org/u/tbillah)\
**Post date:** [July 11, 2019, 10:09pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/3 "2019-07-11T22:09:38Z")

</div>

You mean called `jcfr` ?

> [@jcfr](#):
>
> Assuming the user where Slicer and the extensions are installed is called `slicer`

---

<div class="post-metadata">

**Author:** ![jcfr](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jcfr/32/17825_2.png) [@jcfr](https://discourse.slicer.org/u/jcfr)\
**Post date:** [July 11, 2019, 10:13pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/4 "2019-07-11T22:13:21Z")

</div>

> You mean called `jcfr` ?
> 
> > Assuming the user where Slicer and the extensions are installed is called `slicer`

Indeed, I edited the post to be more clear. Let us know how it works out.

---

<div class="post-metadata">

**Author:** ![tbillah](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tbillah/32/4139_2.png) [@tbillah](https://discourse.slicer.org/u/tbillah)\
**Post date:** [July 20, 2019, 3:17am UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/5 "2019-07-20T03:17:34Z")

</div>

For a week, the environment was down. After it came back online, I tried your instruction. It is mostly correct, except another user would not have access to a file in my home directory:

slicer\_revision\_user\_settings=`/home/${slicer_user}/.config/NA-MIC/Slicer-${revision}.ini`

To get around that, I have done the following:

When you install an extension using the Extension Manager, it allows you to specify a path other than the default `/home/${slicer_user}/.config/NA-MIC/Slicer-${revision}.ini` directory. I have put in a shared path. The Extension got installed, and the above `.ini` file got written as it should be. Then, I just copied over the `.ini` file from my home directory to the shared path.

Rest assured, now I have a way to make Extensions available to all other users that I installed.

---

<div class="post-metadata">

**Author:** ![tbillah](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tbillah/32/4139_2.png) [@tbillah](https://discourse.slicer.org/u/tbillah)\
**Post date:** [July 24, 2019, 3:29pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/6 "2019-07-24T15:29:45Z")

</div>

@jcfr

> ${launcher} --launcher-additional-settings ${slicer\_revision\_user\_settings} --additional-module-paths ${additional\_module\_paths} “$@”

The “$@” is failing here. For example, I have tried the following command with additional arguments, but it fails:

> Slicer-4.10.2-linux-amd64/SlicerWithExtensions.sh --launch python-real SlicerDiffusionQC/Test/run\_test.py

Error message:

```auto
Unknown option: --
usage: /rfanfs/pnl-zorro/software/pnlpipe3/Slicer-4.10.2-linux-amd64/bin/../bin/./python-real [option] ... [-c cmd | -m mod | file | -] [arg] ...
Try `python -h' for more information.

```

I understand you are trying to get any additional argument passed to the script.

---

<div class="post-metadata">

**Author:** ![tbillah](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tbillah/32/4139_2.png) [@tbillah](https://discourse.slicer.org/u/tbillah)\
**Post date:** [September 5, 2019, 8:06pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/7 "2019-09-05T20:06:21Z")

</div>

Upon installing an Extension from ExtensionManager, it appears that `~/.config/NA-MIC/Slicer-{revision}.ini` file gets updated with new `[LibraryPaths]`, `AdditionalPaths`, `[PYTHONPATH]`, `[PATH]` even though I specify a different directory for `Extensions installation path`. Is there a way to compartmentalize where `Slicer-{revision}.ini` file will be written?

The use case is, I have my own Extensions at `~/.config/NA-MIC` while there is a shared Extension path at `~/where/ever/it/is`. Extensions installed at the latter directory are not found by a different user unless a `Slicer-{revision}.ini` exists in a shared directory.

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [September 5, 2019, 8:23pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/8 "2019-09-05T20:23:15Z")

</div>

I think in this case the easiest solution is to make a shell script that uses the --additional-module-paths command line argument to specify all the extensions.

---

<div class="post-metadata">

**Author:** ![tbillah](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tbillah/32/4139_2.png) [@tbillah](https://discourse.slicer.org/u/tbillah)\
**Post date:** [September 5, 2019, 8:26pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/9 "2019-09-05T20:26:49Z")

</div>

Okay, but then someone would have to type in all the extensions, right? In @jcfr’s suggestion, it was more or less automatically discovered.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [September 5, 2019, 8:39pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/10 "2019-09-05T20:39:22Z")

</div>

To compartmentalize settings, you can rename the Slicer executable file (bin/SlicerApp-real). This will create custom .ini files completely independent from Slicer installations. You also need to update Application/path value in bin/SlicerLauncherSettings.ini file accordingly.

To have completely isolated, custom-branded applications, you can build Slicer from source using [this template](https://github.com/KitwareMedical/SlicerCustomAppTemplate).

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [September 5, 2019, 8:42pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/11 "2019-09-05T20:42:53Z")

</div>

> [@tbillah](#):
>
> Okay, but then someone would have to type in all the extensions, right? In @jcfr’s suggestion, it was more or less automatically discovered.

It’s a matter of taste, but there’s a tradeoff here between simplicity and automation. Personally, I think a script that has a lot of identical lines adding paths to the command line is easier to understand and maintain (especially if it’s nicely formatted with backslashes and indentation). There’s only so much that needs to be in such a script.

---

<div class="post-metadata">

**Author:** ![tbillah](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tbillah/32/4139_2.png) [@tbillah](https://discourse.slicer.org/u/tbillah)\
**Post date:** [September 5, 2019, 8:50pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/12 "2019-09-05T20:50:19Z")

</div>

> There’s only so much that needs to be in such a script.

I like your thought. Question on that: see the following excerpt from `Slicer-28257.ini` file:

```auto
[LibraryPaths]
1\path=/rfanfs/pnl-zorro/software/pnlpipe3/Slicer-4.10.2-linux-amd64/.config/NA-MIC/Extensions-28257/DiffusionQC/bin
10\path=/rfanfs/pnl-zorro/software/pnlpipe3/Slicer-4.10.2-linux-amd64/.config/NA-MIC/Extensions-28257/UKFTractography/lib/Slicer-4.10/cli-modules
11\path=/rfanfs/pnl-zorro/software/pnlpipe3/Slicer-4.10.2-linux-amd64/.config/NA-MIC/Extensions-28257/UKFTractography/lib/Slicer-4.10/qt-loadable-modules

```

In the rest of the file, those paths appear multiple times in `[LibraryPaths]` section. Similar multiplicity exists in other sections i.e `[PYTHONPATH]` and `[Paths]`. So, when writing the shell script, can I omit multiplicity of paths? @pieper @lassoan

---

<div class="post-metadata">

**Author:** ![tbillah](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tbillah/32/4139_2.png) [@tbillah](https://discourse.slicer.org/u/tbillah)\
**Post date:** [September 5, 2019, 8:51pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/13 "2019-09-05T20:51:08Z")

</div>

> [@lassoan](#):
>
> To have completely isolated, custom-branded applications, you can build Slicer from source using [this template](https://github.com/KitwareMedical/SlicerCustomAppTemplate).

Built many times so far, but not the sweetest option on a shared cluster without administrative privileges.

I shall try the first part of your suggestion.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [September 5, 2019, 8:59pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/14 "2019-09-05T20:59:10Z")

</div>

If you want to have a shared Slicer with extensions installed, you can also just copy all the extensions in lib\Slicer-4.11 folder. No need to modify any settings or paths.

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [September 5, 2019, 9:04pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/15 "2019-09-05T21:04:12Z")

</div>

If you don’t want to copy the files, you can just list the modules folders in the command line to start slicer.  
I often have a small shell script to start up slicer with extensions under development and just point to their build directories.

I don’t have one handy, but something like:

```auto
Slicer --additional-module-paths \
  ${extdir}/cli-modules \
  ${extdir}/qt-loadable-modules \
  ${extdir}/qt-scripted-modules \

```

all the extensions will follow the same pattern.

---

<div class="post-metadata">

**Author:** ![tbillah](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tbillah/32/4139_2.png) [@tbillah](https://discourse.slicer.org/u/tbillah)\
**Post date:** [October 11, 2019, 4:37pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/16 "2019-10-11T16:37:52Z")

</div>

Hi @pieper, sorry I might be a little late to check on this. I tried the following:

```auto
./Slicer --additional-module-paths .config/NA-MIC/Extensions-28257/DiffusionQC/lib/Slicer-4.10/cli-modules/ .config/NA-MIC/Extensions-28257/DiffusionQC/lib/Slicer-4.10/qt-scripted-modules/ --launch bin/python-real .config/NA-MIC/Extensions-28257/DiffusionQC/lib/Slicer-4.10/cli-modules/diffusionQC.py -h

```

But ran into the error:

```auto
Usage
  Slicer [options]

Options
  --launcher-help Display help
  --launcher-version Show launcher version information
  --launcher-verbose Verbose mode
  --launch Specify the application to launch
  --launcher-detach Launcher will NOT wait for the application to finish
  --launcher-no-splash Hide launcher splash
  --launcher-timeout Specify the time in second before the launcher kills the application. -1 means no timeout (default: -1)
  --launcher-load-environment Specify the saved environment to load.
  --launcher-dump-environment Launcher will print environment variables to be set, then exit
  --launcher-show-set-environment-commands Launcher will print commands suitable for setting the parent environment (i.e. using 'eval' in a POSIX shell), then exit
  --launcher-additional-settings Additional settings file to consider
  --launcher-additional-settings-exclude-groups Comma separated list of settings groups that should NOT be overwritten by values in User and Additional settings. For example: General,Application,ExtraApplicationToLaunch
  --launcher-ignore-user-additional-settings Ignore additional user settings
  --launcher-generate-exec-wrapper-script Generate executable wrapper script allowing to set the environment
  --launcher-generate-template Generate an example of setting file
  --designer Start Qt designer using Slicer plugins
Unknown option: --
usage: bin/python-real [option] ... [-c cmd | -m mod | file | -] [arg] ...
Try `python -h' for more information.

```

So, am I not using it the right way?

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [October 11, 2019, 5:32pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/17 "2019-10-11T17:32:49Z")

</div>

Ah, right - the problem here is that `--additional-module-paths` is an argument of the application, not the launcher. But I see here you are wanting to launch `bin/python-real` .

Probably you want something more like this, where you use the app as a python environment to it has the extensions loaded.

```auto
EXT_DIR=.config/NA-MIC/Extensions-28257/DiffusionQC/lib/Slicer-4.10

./Slicer-build/Slicer \
  --no-main-window \
  --python-script ${EXT_DIR}/cli-modules/diffusionQC.py \
  --additional-module-paths \
      ${EXT_DIR}/cli-modules/ \
      ${EXT_DIR}/qt-scripted-modules/

```

---

<div class="post-metadata">

**Author:** ![tbillah](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tbillah/32/4139_2.png) [@tbillah](https://discourse.slicer.org/u/tbillah)\
**Post date:** [October 11, 2019, 6:56pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/18 "2019-10-11T18:56:27Z")

</div>

The suggestion ran into following error (I am connected via SSH though):

```auto
qt.qpa.screen: QXcbConnection: Could not connect to display
Could not connect to any X display.

```

The point of trying to run a script like above is to omit Slicer GUI.

I also tried the following (`--additional-module-paths` as an argument for the application now), but failed with the same error:

```auto
./Slicer --additional-module-paths ${EXT_DIR}/cli-modules/ ${EXT_DIR}/qt-scripted-modules/ --launch python-real ${EXT_DIR}/cli-modules/diffusionQC.py -h

```

```auto
Unknown option: --
usage: /rfanfs/pnl-zorro/software/pnlpipe3/Slicer-4.10.2-linux-amd64/bin/../bin/./python-real [option] ... [-c cmd | -m mod | file | -] [arg] ...
Try `python -h' for more information.

```

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [October 11, 2019, 7:14pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/19 "2019-10-11T19:14:07Z")

</div>

Probably easiest just to install and run [Xdummy](https://xpra.org/trac/wiki/Xdummy). You shouldn’t need any of the GLX options if you just want to run the script.

---

<div class="post-metadata">

**Author:** ![tbillah](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/tbillah/32/4139_2.png) [@tbillah](https://discourse.slicer.org/u/tbillah)\
**Post date:** [October 11, 2019, 8:01pm UTC](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511/20 "2019-10-11T20:01:50Z")

</div>

Okay, solved the X error. Now, how would I provide argument to the python-script I want to run?

> ./Slicer --additional-module-paths ${EXT\_DIR}/cli-modules/ ${EXT\_DIR}/qt-scripted-modules/ --no-main-window --python-script ${EXT\_DIR}/cli-modules/diffusionQC.py -h

The above prints Slicer’s help message, not the one from the python-script.

[Next page](https://discourse.slicer.org/t/installing-extensions-in-binary-distribution-of-slicer/7511.md?page=2)
