<?xml version="1.0" encoding="ISO-8859-1" ?>

<rdf:RDF
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  xmlns:admin="http://webns.net/mvcb/"
  xmlns:cc="http://web.resource.org/cc/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns="http://purl.org/rss/1.0/">

<channel rdf:about="http://planete.xulfr.org/">
  <title>Planète Xulfr</title>
  <description></description>
  <link>http://planete.xulfr.org/</link>
  <dc:language>fr-fr</dc:language>
  <dc:creator></dc:creator>
  <dc:rights></dc:rights>
  <dc:date>2011-06-28T18:12:19+00:00</dc:date>
  <admin:generatorAgent rdf:resource="http://planete.xulfr.org/" />


  <items>
  <rdf:Seq>
             <rdf:li rdf:resource="http://blog.queze.net/n293-instantbird-1-0-sorti-simultanement-en-11-langues-dont-le-francais-evidemment-13.html"/>
                <rdf:li rdf:resource="http://joliclic.free.fr/blog/index.php?post/2011/05/27/Distribuer-votre-appli-XULRunner-5-Synthese-toutes-plateformes"/>
                <rdf:li rdf:resource="http://joliclic.free.fr/blog/index.php?post/2011/05/27/Distribute-your-XULRunner-app-5-Synthesis-all-platforms"/>
                <rdf:li rdf:resource="http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribuer-votre-appli-XULRunner-4-Mac-OSX"/>
                <rdf:li rdf:resource="http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribute-your-XULRunner-app-4-Mac-OSX"/>
                <rdf:li rdf:resource="http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribuer-votre-appli-XULRunner-3-Windows"/>
                <rdf:li rdf:resource="http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribute-your-XULRunner-app-3-Windows"/>
                <rdf:li rdf:resource="http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribuer-votre-appli-XULRunner-24-Empaqueter-un-rpm"/>
                <rdf:li rdf:resource="http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribute-your-XULRunner-app-24-Package-as-rpm"/>
                <rdf:li rdf:resource="http://joliclic.free.fr/blog/index.php?post/2011/05/23/Distribuer-votre-appli-XULRunner-23-Un-cas-special-deb-pour-Maemo"/>
                <rdf:li rdf:resource="http://joliclic.free.fr/blog/index.php?post/2011/05/23/Distribute-your-XULRunner-app-23-Special-case-deb-for-Maemo"/>
          </rdf:Seq>
  </items>
</channel>
  <item rdf:about="http://blog.queze.net/n293-instantbird-1-0-sorti-simultanement-en-11-langues-dont-le-francais-evidemment-13.html">
    <title>Instantbird 1.0, sorti simultanément en 11 langues (dont le français évidemment)</title>
    <link>http://blog.queze.net/n293-instantbird-1-0-sorti-simultanement-en-11-langues-dont-le-francais-evidemment-13.html</link>
    <dc:date>2011-06-28T18:12:19+00:00</dc:date>
    <dc:language>fr</dc:language>
    <dc:creator>Blog@queze.net - Mozilla</dc:creator>
    <dc:subject></dc:subject>
	<description>
   &lt;p&gt;&lt;a href=&quot;http://instantbird.com/&quot;&gt;Instantbird 1.0&lt;/a&gt; vient de sortir.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.instantbird.com/&quot;&gt;&lt;img src=&quot;http://www.instantbird.com/press/logos/instantbird-text-512x128.png&quot; alt=&quot;Instantbird logo&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Cette version apporte de très nombreuses améliorations. Cette fois ci, non seulement le logiciel en lui-même est traduit, mais le site web aussi, alors pour savoir ce qui est changé depuis la version précédente, il suffit donc tout simplement d'&lt;a href=&quot;http://www.instantbird.com/release-notes.html&quot;&gt;aller voir sur le site d'Instantbird&lt;/a&gt; lui-même &lt;img src=&quot;smileys/sourire.png&quot; alt=&quot;:)&quot; /&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.instantbird.com/&quot;&gt;&lt;img src=&quot;http://www.instantbird.com/press/screenshots/1.0-winaero-screenshot-homepage-big.png&quot; alt=&quot;Instantbird 1.0 - copie d'écran sur Windows 7&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De nombreux blogs reprennent déjà l'information. N'hésitez pas à faire de même (ou à partager sur Facebook ou twitter) afin que vos amis en profitent aussi&amp;nbsp;!&lt;/p&gt;
</description>
	<content:encoded><![CDATA[
   <p><a href="http://instantbird.com/">Instantbird 1.0</a> vient de sortir.</p>
<p><a href="http://www.instantbird.com/"><img src="http://www.instantbird.com/press/logos/instantbird-text-512x128.png" alt="Instantbird logo" /></a></p>
<p>Cette version apporte de très nombreuses améliorations. Cette fois ci, non seulement le logiciel en lui-même est traduit, mais le site web aussi, alors pour savoir ce qui est changé depuis la version précédente, il suffit donc tout simplement d'<a href="http://www.instantbird.com/release-notes.html">aller voir sur le site d'Instantbird</a> lui-même <img src="smileys/sourire.png" alt=":)" />.</p>

<p><a href="http://www.instantbird.com/"><img src="http://www.instantbird.com/press/screenshots/1.0-winaero-screenshot-homepage-big.png" alt="Instantbird 1.0 - copie d'écran sur Windows 7"/></a></p>

<p>De nombreux blogs reprennent déjà l'information. N'hésitez pas à faire de même (ou à partager sur Facebook ou twitter) afin que vos amis en profitent aussi&nbsp;!</p>
]]></content:encoded>
</item>
     <item rdf:about="http://joliclic.free.fr/blog/index.php?post/2011/05/27/Distribuer-votre-appli-XULRunner-5-Synthese-toutes-plateformes">
    <title>Distribuer votre appli XULRunner - 5 - Synthèse - toutes plateformes</title>
    <link>http://joliclic.free.fr/blog/index.php?post/2011/05/27/Distribuer-votre-appli-XULRunner-5-Synthese-toutes-plateformes</link>
    <dc:date>2011-05-27T17:43:00+00:00</dc:date>
    <dc:language>fr</dc:language>
    <dc:creator>Joliclic blog - mozilla</dc:creator>
    <dc:subject></dc:subject>
	<description></description>
	<content:encoded><![CDATA[    <div class="howto">
<p><em>This post exists also in <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/Distribute-your-XULRunner-app-5-Synthesis-all-platforms">english</a></em></p>
<p><em>
Ce billet fait partie d'une <a href="http://joliclic.free.fr/blog/index.php?tag/dist_xul_app_fr">série</a> sur comment déployer une application XULRunner.
Voir le <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/20/Distribuer-votre-appli-XULRunner-1-Preambule">préambule</a> pour le contexte.
</em></p>
<h3><span>5 - Synthèse - toutes plateformes</span></h3>
<ul>
<li>5.1 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/#howtofr_dxr_5.1">Changements dans l'appli</a></li>
<li>5.2 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/#howtofr_dxr_5.2">Données ajoutées</a></li>
<li>5.3 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/#howtofr_dxr_5.3">Installeurs créés</a></li>
<li>5.4 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/#howtofr_dxr_5.4">Un script global et réutilisable</a></li>
<li>5.5 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/#howtofr_dxr_5.5">Conclusions</a></li>
</ul>
<div class="howto-section">
<h4><span>5.1 Changements dans l'appli</span></h4>
<p>
Résumons les changements que nous avons apporté à l'application elle-même,
pour chaque plateforme&nbsp;:
</p>
<ul>
<li>
<h5>Linux</h5>
<ul>
<li>
<p>
Nous avons <strong>ajouté quelques icônes png</strong>
dans le dossier <code>myapp/chrome/icons/default/</code> .
<br />
Ceci permet d'avoir notre icône pour nos fenêtres et dans
la barre de tâche.
<br />
En details, 16x16px, 32x32px et 48x48px.
</p>
<p><em>
Nous pouvons conserver ces changements globalement, ils
n'auront pas d'impact sur les autres plateformes.
</em></p>
</li>
</ul>
</li>
<li>
<h5>Windows</h5>
<ul>
<li>
<p>
De manière similaire à Linux, nous avons
<strong>ajouté quelques icônes .ico</strong> dans le dossier
<code>myapp/chrome/icons/default/</code>, pour les mêmes raisons.
<br />
Et nous avons créer cette icône depuis Linux avec le programme
<code>icotool</code>.
</p>
<p><em>
Nous pouvons conserver ces changements globalement, ils n'auront
pas d'impact sur les autres plateformes.
</em></p>
</li>
</ul>
</li>
<li>
<h5>Mac OSX</h5>
<ul>
<li>
<p>
Nous avons <strong>ajouté un élément menubar principal</strong>
dans toutes nos fenêtres non modales, avec
<strong>quelques entrées avec un <code>id</code> spécifique</strong>.
<br />
Ceci nous permet d'avoir nos propres entrées dans le
Menu principal Mac.
<br />
Ces entrées sont masquées (d'un point de vue XUL) par défaut.
</p>
<p><em>
Nous pouvons conserver ces changements globalement, ils n'auront
pas d'impact sur les autres plateformes, parce ces éléments XUL
sont masqués pour les autres plateformes.
</em></p>
</li>
<li>
<p>
Nous avons <strong>ajouté un peu de code JavaScript</strong>
à notre fichier js principal. Parce que sur un Mac l'appli ne quitte
pas quand on ferme toutes les fenêtres.
</p>
<p><em>
Nous pouvons conserver ces changements globalement, le code
est multi-plateforme. Mieux, nous pouvons l'utiliser également
sur les autres plateformes.
</em></p>
</li>
<li>
<p>
Nous avons <strong>ajouté un nouveau fichier, une fenêtre XUL masquée</strong>.
Cette fenêtre est utilisée pour granir le Menu Mac principal quand toutes
nos fenêtres sont fermées.
</p>
<p><em>
Nous pouvons conserver ces changements globalement, ils n'auront
pas d'impact sur les autres plateformes.
</em></p>
</li>
<li>
<p>
Et nous avons <strong>ajouté une préférence</strong>
(<code>browser.hiddenWindowChromeURL</code>),
pour utiliser la fenêtre cachée précédente.
</p>
<p><em>
Nous pouvons conserver ces changements globalement, ils n'auront
pas d'impact sur les autres plateformes.
</em></p>
</li>
</ul>
</li>
</ul>
<p>
Donc, finalement, ce sont de petits changements, et tous peuvent être ajouté
globalement, car ils ne perturbent pas les plateformes non ciblées.
</p>
</div>
<div class="howto-section">
<h4><span>5.2 Données ajoutées</span></h4>
<p>
Pour une meilleure intégration aux différentes platformes, nous avons ajouté
quelques données supplémentaires&nbsp;:
</p>
<ul>
<li>
<h5>Linux</h5>
<ul>
<li>
<p>
Un <strong>script shell utilisé comme lanceur</strong>,
qui utilise de XULRunner ou de Firefox
<br />
Un lien symbolique vers ce lanceur dans
<code>/usr/bin/</code> est également créé par nos
installeurs.
</p>
</li>
<li>
<p>
Un <strong>fichier .desktop</strong>,
A <strong>.desktop file</strong>, pour l'intégration au bureau,
compris par tous les gestionnaires de fenêtre principaux.
</p>
</li>
<li>
<p>
et <strong>quelques icônes</strong> (png et svg), utilisées
par les fichiers desktop.
</p>
</li>
</ul>
</li>
<li>
<h5>Windows</h5>
<ul>
<li>
<p>
Un <strong>vrai lanceur en C</strong>, en fait
<a href="http://joliclic.free.fr/mozilla/xal/" rel="external">XAL</a>
(XUL App Launcher), qui permet de lancer facilement notre appli
avec Firefox, sans aucune fenêtre noire de commande, et qui
peut être personnalisé avec noytre icône.
<br />
Ce lanceur peut être  compilé directement depuis Linux.
</p>
</li>
<li>
<p>
Un script batch comme lanceur est également possible,
mais avec les défauts inhérents.
</p>
</li>
</ul>
</li>
<li>
<h5>Mac OSX</h5>
<ul>
<li>
<p>
Pour cette platforme, nous avons en fait encapsulé
notre appli dans un dossier avec une structure spéciale,
avec quelques données, un <strong>Application Bundle</strong>
</p>
</li>
<li>
<p>
Un <strong>script shell utilisé comme lanceur</strong>,
qui utilise Firefox (en fait un lien symbolique vers lui, placé
dans notre bundle)
</p>
</li>
<li>
<p>
Une<strong>icône icns</strong>, utilisée par le bundle pour
l'exécutable et dans le dock.
<br />
et nous avons créer cette icône depuis Linux avec le programme
<code>png2icns</code>.
</p>
</li>
<li>
<p>
Un fichier <strong>Info.plist</strong> et un fichier <strong>PkgInfo</strong>,
décrivant le bundle.
</p>
</li>
</ul>
</li>
</ul>
</div>
<div class="howto-section">
<h4><span>5.3 Installeurs créés</span></h4>
<ul>
<li>
<h5>Multi-plateformes</h5>
<p>
Pas de réelle intégration au bureau, et avec quelques limitations
importante sur Mac, mais un <strong>tar.gz</strong> fonctionne et est simple.
</p>
</li>
<li>
<h5>Linux</h5>
<p>
Nous avons créé un paquet <strong>deb</strong> pour les distributions
basées sur Debian/Ubuntu, un deb similaire pour <strong>Maemo</strong>,
et un <strong>rpm</strong> pour les distributions basées sur Red Hat/Fedora.
</p>
</li>
<li>
<h5>Windows</h5>
<p>
Nous avons créer un vrai installeur/désinstalleur, directement depuis Linux,
basé sur <strong>NSIS</strong>.
</p>
</li>
<li>
<h5>Mac OSX</h5>
<p>
Le mode de distribution le plus convivial sur Mac, est de créer un
<strong>dmg</strong>. Nous avons pu le créer depuis Linux, et
avec un programme expérimental, de le compresser.
</p>
<p>
Un simple tar.gz a aussi été créé.
</p>
</li>
</ul>
</div>
<div class="howto-section">
<h4><span>5.4 Un script global et réutilisable</span></h4>
<p>
Dans chaque chapitres, nous avons utilisés des scripts bash pour créer
tous nos installeurs et autres données.
<br />
Je vous propose maintenant un script global pour réaliser toutes ces tâches
en une fois.
</p>
<p>
Plus, ce script peut être utilisé pour tout autre application XULRunner,
nous avons juste à modifier un fichier de configuration.
</p>
<p>
Je n'écris ce script ici, vous le trouverez dans l'archive jointe à ce chapitre,
mais voilà le fichier de configuration&nbsp;:
</p>
<pre>#!/bin/bash<br /><br />#_______________________________________________________________________________<br />#<br /># script version: 1.0<br /># date: 2011-05-20<br />#_______________________________________________________________________________<br /><br /># exit the script on errors<br />set -e<br /><br />#_______________________________________________________________________________<br />#<br /># common configuration<br />#_______________________________________________________________________________<br /><br /># The name of the application, will be the name of the executable for example.<br /># It should contain only [a-zA-Z_-.] and no whitespace.<br />APP_NAME=myapp<br /><br /># The name of the application displayed on screen.<br />APP_DISPLAY_NAME=MyApp<br /><br /># The absolute path to the directory containing this script. Don't modify this<br /># variable if you don't know what you are doing.<br />CUR_DIR=$(dirname "$0")<br />CUR_DIR=$(readlink -f -- "$CUR_DIR")<br /><br /># The main folder of the sources (absolute path), containing the app, data,...<br /># Can be defined before, in some other scripts.<br />if [ ! $MAIN_DIR ]; then<br />    MAIN_DIR=$(readlink -f -- "$CUR_DIR/..")<br />fi<br /><br /># The folder where all resulted builds (installers, archives,...) will be copied<br />DIST_DIR=$MAIN_DIR/dist<br /><br /># The temporary folder where all build are done<br />TMP_DIR=$MAIN_DIR/tmp<br /><br /># Folder which contains extra useful programs for the build script<br />TOOLS_DIR=$MAIN_DIR/tools<br /><br /># Folder which contains all build scripts, and the current config file<br />BUILDERS_DIR=$MAIN_DIR/builders<br /><br /># The folder of the real sources of the XULRunner application<br />APP_SRC_DIR=$MAIN_DIR/$APP_NAME<br /><br /># The folder of the extra data of the app (icons,...)<br />APP_DATA_DIR=$MAIN_DIR/data<br /><br /># The folder of the used icons<br /># This folder must contains:<br /># icon16.png, icon22.png, icon26.png, icon32.png, icon40.png, icon48.png,<br /># icon128.png, icon48.svg, icon.ico, icon.icns, icon48.txt<br /># You can find some shell scripts in the data/icons folder to create the ico,<br /># icns et base64 icons.<br />APP_ICON_DIR=$APP_DATA_DIR/icons<br /><br /># The current version of the app<br />APP_VERSION=1.0<br /><br /># You can use a file named version in the main directory too, and uncomment the<br /># following line to set this variable<br />#APP_VERSION=$(cat "$MAIN_DIR/version")<br /><br /># if the app contains some compiled code, and so it's architecture dependent,<br /># uncomment the following line<br />#ARCH_DEPENDENT=1<br /><br /><br />#_______________________________________________________________________________<br />#<br /># Linux specific<br />#_______________________________________________________________________________<br /><br /># the folder which contains the Linux specifics data<br />LINUX_DIR=$APP_DATA_DIR/linux<br /><br /># the desktop file, will be renamed as $APP_NAME.desktop<br />DESKTOP_FILE=$LINUX_DIR/desktop<br /><br /># If this variable is set, the desktop file will be adapted, i.e. the strings<br /># @@APP_VERSION@@, @@APP_NAME@@, @@APP_DISPLAY_NAME@@, and<br /># @@APP_DESKTOP_CATEGORIE@@,..., will be replaced by their values. Simply<br /># comment the following line to not use this feature.<br />OPT_ADAPT_DESKTOP=1<br /><br /># this value is displayed in a tooltip by the desktop<br />APP_DESKTOP_COMMENT="a Hello World XULRunner app"<br /><br /># A value chosen in http://standards.freedesktop.org/menu-spec/latest/apa.html<br /># If you use multiple value, use a semicolon (;) as separator<br /># DON'T forget the last semicolon, even if there is only one value<br />APP_DESKTOP_CATEGORIE='Utility;'<br /><br /># You can use this variable to put extra lines to the Desktop file, for example<br /># a localized comment<br />APP_DESKTOP_EXTRA='Comment[fr]=un Bonjour Monde pour XULRunner.\n'<br /><br /># the generic Linux launcher, a shell script, for our app. Will be renamed as<br /># $APP_NAME.sh<br />LINUX_LAUNCHER=$LINUX_DIR/launcher.sh<br /><br /><br />#_______________________________________________________________________________<br />#<br /># deb package specific<br />#_______________________________________________________________________________<br /><br /># Comment the following line if you don't want to generate a deb package<br />OPT_BUILD_DEB=1<br /><br /># the debian folder used to build our generic deb<br />DEBIAN_DIR=$APP_DATA_DIR/debian<br /><br /># If this variable is set, the files 'changelog', 'control', 'menu',<br /># 'myapp.link', and 'copyright' of the debian folder will<br /># be adapted, i.e. the strings @@APP_VERSION@@, @@APP_NAME@@,<br /># @@APP_DISPLAY_NAME@@, @@DEB_CONTROL_VERSION@@, @@DEB_CONTROL_SECTION@@,<br /># @@DEB_MENU_SECTION@@, ..., will be replaced by their values. Simply comment<br /># the following line to not use this feature.<br />OPT_ADAPT_DEBIAN=1<br /><br /># The version of the generated deb package.<br />DEB_CONTROL_VERSION=${APP_VERSION}-1<br /><br /># the category of the app. See http://packages.debian.org/en/sid/<br />DEB_CONTROL_SECTION=Utilities<br /><br />DEB_CONTROL_MAINTAINER='John Doe &lt;johndoe@example.com&gt;'<br /><br /># author of the generated deb<br />DEB_CONTROL_AUTHOR=$DEB_CONTROL_MAINTAINER<br /><br />DEB_CONTROL_HOMEPAGE='&lt;http://example.com/myapp/&gt;'<br /><br /># name of the generated package<br />DEB_CONTROL_PACKAGE=$APP_NAME<br /><br /># long description of the app for the generated deb. Can be multiline, see<br /># http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Description<br /># for the formatting (in short, add at least a space at the beginning of all<br /># lines apart the first)<br />DEB_CONTROL_DESCRIPTION='simple Hello World.<br /> Powered by XULRunner.'<br /><br /># if the app have other dependencies than Firefox, list them, separated by a<br /># comma. Important, this list MUST begin by a comma.<br />DEB_CONTROL_EXTRA_DEPENDENCIES=<br /><br /># if the app contains some compiled code, and you want to use the<br /># ${shlibs:Depends} variable with debhelper, uncomment the following line<br />#DEB_CONTROL_USE_SHLIBS_DEPENDS=1<br /><br /># the category for the Debian menu, see<br /># http://www.debian.org/doc/packaging-manuals/menu-policy/ch2.html#s2.1<br />DEB_MENU_SECTION='Applications/Programming'<br /><br />DEB_DATE="$(date -R)"<br /><br />DEB_COPYRIGHT='&lt;Copyright (C) 2010 John Doe&gt;'<br /><br /># the short license for the generated deb<br />DEB_SHORT_LICENSE=$(cat "$LINUX_DIR/deb_short_license.txt")<br /><br /><br />#_______________________________________________________________________________<br />#<br /># maemo deb specific<br />#_______________________________________________________________________________<br /><br /># Note that the debian specific variables are used as well to generate the<br /># maemo deb, so they must set.<br /><br /># the APP_NAME specific for Maemo, can be the same as APP_NAME<br />MOBILE_APP_NAME=$APP_NAME<br /><br /># the APP_DISPLAY_NAME specific for Maemo, can be the same as APP_DISPLAY_NAME<br />MOBILE_APP_DISPLAY_NAME=$APP_DISPLAY_NAME<br /><br /># the name of the app for the package. Should be different than APP_NAME,<br /># otherwise there can be collision with the generic deb created by the other<br /># script<br />MAEMO_PKG_APPNAME=${APP_NAME}-mobile<br /><br /># the desktop file for Maemo, will be renamed as $APP_NAME.desktop<br />MAEMO_DESKTOP_FILE=$LINUX_DIR/maemodesktop<br /><br /># the launcher for Maemo, a shell script, for our app. Will be renamed as<br /># $APP_NAME.sh<br />MAEMO_LAUNCHER=$LINUX_DIR/maemolauncher.sh<br /><br /># Comment the following line if you don't want to generate a deb package<br />OPT_BUILD_MAEMO_DEB=1<br /><br /># the debian folder used to build our deb for Maemo<br />MAEMODEBIAN_DIR=$APP_DATA_DIR/maemodebian<br /><br /># the categorie of the app for Maemo. See<br /># http://wiki.maemo.org/Packaging/Guidelines#Sections<br />DEB_CONTROL_SECTION_MAEMO=user/utilities<br /><br /># the name of the generated deb for Maemo.<br /># Should really the same as MAEMO_PKG_APPNAME, see its comment.<br />DEB_CONTROL_PACKAGE_MAEMO=$MAEMO_PKG_APPNAME<br /><br /># the description of the generated deb, especially for Maemo. See the comments<br /># for DEB_CONTROL_DESCRIPTION in this file for formatting.<br />DEB_CONTROL_DESCRIPTION_MAEMO=$DEB_CONTROL_DESCRIPTION<br /><br /># like DEB_CONTROL_EXTRA_DEPENDENCIES, but for Maemo<br />DEB_CONTROL_EXTRA_DEPENDENCIES_MAEMO=<br /><br /># the base64 file (text) of the icon for the Maemo deb.<br /># Can be generated by the script 'build_icon_base64.sh' in the data/icons dir.<br />MAEMO_BASE64_ICON="$APP_ICON_DIR/icon48.txt"<br /><br /><br />#_______________________________________________________________________________<br />#<br /># rpm package specific<br />#_______________________________________________________________________________<br /><br /># Comment the following line if you don't want to generate a rpm package<br />OPT_BUILD_RPM=1<br /><br /># path to the spec file used to generate the rpm<br />RPM_SPEC_FILE=$LINUX_DIR/rpmspec<br /><br /># If this variable is set, the .spec file will<br /># be adapted, i.e. the strings @@APP_VERSION@@, @@APP_NAME@@,<br /># @@APP_DISPLAY_NAME@@, @@RPM_VERSION@@, @@RPM_RELEASE@@, @@RPM_GROUP@@,<br /># @@RPM_LICENSE@@, @@RPM_URL@@, @@RPM_SOURCE@@, @@RPM_DATE@@, ...<br /># will be replaced by their values. Simply comment the following line to not use<br /># this feature.<br />OPT_ADAPT_RPM=1<br /><br /># version of the app for the spec file: must contain only integer and digit, no<br /># strings like 'beta'<br />RPM_VERSION=$APP_VERSION<br /><br /># the version of the generated rpm, not the app version<br />RPM_RELEASE='1%{?dist}'<br /><br /># the short version of the generated rpm, without any string relative to the<br /># distribution or architecture<br />#RPM_RELEASE_SHORT=1<br />RPM_RELEASE_SHORT=$(echo $RPM_RELEASE | sed "s/%.*$//")<br /><br /># breve summary of the app for the package. One line only.<br />RPM_SUMMARY='simple Hello World powered by XULRunner.'<br /><br /># the category of the app. See /usr/share/doc/rpm/GROUPS<br />RPM_GROUP=Development/Tools<br /><br /># keyword license<br />RPM_LICENSE='MPLv1.1 or GPLv2+ or LGPLv2+'<br /><br /># url where the source of our app can be found<br />RPM_URL='http://example.com/myapp/'<br /><br /># the name of the dummy tar.gz source archive, it will be built by this script.<br />RPM_SOURCE=${APP_NAME}-${RPM_VERSION}.tar.gz<br /><br /># If the app need some build dependencies, uncomment the following line and add<br /># them here, separated by a comma. BUT you shouldn't have to, the logic here is<br /># that the built should have been done before, this script simply package the<br /># result.<br />#RPM_BUILDREQUIRES=<br /><br /># if the app have other dependencies than Firefox, list them, separated by a<br /># comma. Important, this list MUST begin by a comma.<br />RPM_EXTRA_REQUIRES=<br /><br /># long description of the app for the generated rpm. Can be multiline.<br />RPM_DESCRIPTION='simple Hello World<br />Powered by XULRunner.'<br /><br />LC_TIME_BUFFER=$LC_TIME<br />export LC_TIME="en_EN.utf8"<br />RPM_DATE=$(date +"%a %b %e %Y")<br />export LC_TIME="$LC_TIME_BUFFER"<br /><br />RPM_MAINTAINER='John Doe &lt;johndoe@example.com&gt;'<br /><br /><br />#_______________________________________________________________________________<br />#<br /># Windows specific<br />#_______________________________________________________________________________<br /><br /># the folder which contains the Windows specifics data<br />WIN_DIR=$APP_DATA_DIR/win<br /><br /># the version of the app used by some other variables. String.<br />WIN_VERSION=$APP_VERSION<br /><br /># comment this line if you don't want to build xal, the launcher in C<br />OPT_BUILD_WIN_XAL=1<br /><br /># source directory of xal<br />XAL_SRC_DIR=$TOOLS_DIR/xal-src<br /><br /># the rc file used to build xal<br />WIN_RESOURCE=$WIN_DIR/resource.rc<br /><br /># If this variable is set, the resource (.rc) file for xal will<br /># be adapted, i.e. the strings @@APP_VERSION@@, @@APP_NAME@@,<br /># @@APP_DISPLAY_NAME@@, and @@WINRES_...@@<br /># will be replaced by their values. Simply comment the following line to not use<br /># this feature.<br />OPT_ADAPT_WINRES=1<br /><br />WINRES_FILEVERSION='0,1,0,0'<br /># the FILEVERSION for Windows (&lt;int,int,int,int&gt;) will be deducted from the<br /># APP_VERSION. Comment this line if you don't want use this feature<br />OPT_CALC_WINRES_FVERSION=1<br /><br />WINRES_PRODUCTVERSION='0,1,0,0'<br /># the PRODUCTVERSION for Windows (&lt;int,int,int,int&gt;) will be deducted from the<br /># APP_VERSION. Comment this line if you don't want use this feature<br />OPT_CALC_WINRES_PVERSION=1<br /><br />WINRES_Comments='Published under the MPL 1.1/GPL 2.0/LGPL 2.1 licenses'<br />WINRES_CompanyName='John Doe Organization'<br />WINRES_FileDescription=$APP_DISPLAY_NAME<br />WINRES_FileVersion=$WIN_VERSION<br />WINRES_InternalName=$APP_NAME<br />WINRES_LegalCopyright='(c) 2010 John Doe'<br />WINRES_ProductName=$APP_DISPLAY_NAME<br />WINRES_ProductVersion=$WIN_VERSION<br /><br /># Comment the following line if you don't want to generate the nsis installer<br /># for Windows<br />OPT_BUILD_WIN_INSTALLER=1<br /><br /># the source folder of the nsis scripts used by this script<br />NSIS_SRC_DIR=$APP_DATA_DIR/nsis<br /><br /># If this variable is set, the nsis script will<br /># be adapted, i.e. the strings @@APP_VERSION@@, @@APP_NAME@@,<br /># @@APP_DISPLAY_NAME@@, and @@NSIS_...@@<br /># will be replaced by their values. Simply comment the following line to not use<br /># this feature.<br />OPT_ADAPT_NSIS=1<br /><br />NSIS_PRODUCT_NAME=$APP_DISPLAY_NAME<br />NSIS_PRODUCT_INTERNAL_NAME=$APP_NAME<br />NSIS_PRODUCT_VERSION=$WIN_VERSION<br />NSIS_PRODUCT_WIN_VERSION='1.0.0.0'<br /># for nsis, the PRODUCTVERSION for Windows (&lt;int,int,int,int&gt;) will be deducted<br /># from the APP_VERSION. Comment this line if you don't want use this feature<br />OPT_CALC_NSIS_WINVERSION=1<br /><br /># The license file text MUST be in the main root app folder, so in $APP_SRC_DIR.<br /># Otherwise, you can edit the nsis script and adapt it<br />NSIS_LICENCE_NAME='LICENSE.txt'<br /><br /># the name of the generated nsis installer<br />NSIS_INSTALLER_NAME="$APP_DISPLAY_NAME-$APP_VERSION-install.exe"<br /><br /><br />#_______________________________________________________________________________<br />#<br /># Mac OSX specific<br />#_______________________________________________________________________________<br /><br /># the folder which contains the Mac OSX specifics data<br />MAC_DIR=$APP_DATA_DIR/mac<br /><br /># the simple and basic shell launcher for Mac. Used only for the<br /># multiplatform tar.gz<br />MAC_BASIC_LAUNCHER=$MAC_DIR/basic_launcher.sh<br /><br /># the previous basic launcher will be renamed with this value<br /># Trick: if the extension is 'command', the file can double-clicked in the Mac<br /># Finder, then a terminal will be opened and the script will be launched.<br />MAC_BASIC_LAUNCHER_NAME=${APP_NAME}-mac.command<br /><br /># Comment the following line if you don't want to generate the Application<br /># Bundle of the app for Mac.<br />OPT_BUILD_MAC_BUNDLE=1<br /><br /># path to the used skeleton of the bundle<br />DMG_SKELET_DIR=$MAC_DIR/bundle_skelet<br /><br /># If this variable is set, the nsis script will<br /># be adapted, i.e. the strings @@APP_VERSION@@, @@APP_NAME@@,<br /># @@APP_DISPLAY_NAME@@, and @@MAC_...@@<br /># will be replaced by their values. Simply comment the following line to not use<br /># this feature.<br />OPT_ADAPT_MAC_INFO=1<br /><br />MAC_BUNDLE_EXECUTABLE=${APP_NAME}-mac.sh<br />MAC_BUNDLE_INFOSTRING="$APP_DISPLAY_NAME $APP_VERSION"<br />MAC_BUNDLE_ICONFILE=$APP_NAME<br />MAC_BUNDLE_IDENTIFIER="net.yourcompany.${APP_NAME}"<br />MAC_BUNDLE_NAME=$APP_DISPLAY_NAME<br />MAC_BUNDLE_SHORTVERSIONSTRING=$APP_VERSION<br />MAC_BUNDLE_VERSION=$APP_VERSION<br /><br /># with this option, the eventual icon 'myapp.icns' in the Contents/Resources<br /># folder of the used bundle skelet will be removed, and the icns icon of the<br /># icons folder will be added to the bundle renamed as MAC_BUNDLE_ICONFILE<br />MAC_BUNDLE_OVERWRITE_ICON=1<br /><br /># comment the following line if you don't want to generate a dmg image <br />OPT_BUILD_MAC_DMG=1<br /># comment the following line if you don't want to customize the dmg image <br />OPT_CUSTOMIZE_DMG=1<br /># source folder of the data added to the dmg, to customize it<br /># Note that you have to recreate manually these customizations files if the<br /># DMG_VOLNAME is different than 'MyApp', in particular the background image<br /># will not be displayed. See the Howto.<br /># Comment the line to disabled this option.<br />DMG_CUSTOM_DATA_DIR=$MAC_DIR/dmg_extra_data<br /><br /># the name of the mounted dmg disk image<br />DMG_VOLNAME="$APP_DISPLAY_NAME"<br /># the name of the generated dmg<br />DMG_NAME="$APP_NAME-$APP_VERSION.dmg"<br /><br /># comment the following line if you don't want to compress the dmg. You need<br /># the &lt;dmg&gt; program to be able to do that<br />OPT_COMPRESS_DMG=1<br /># path to the dmg program, used to compress the dmg.<br /># see http://github.com/planetbeing/libdmg-hfsplus<br /># and http://shanemcc.co.uk/libdmg/<br />TOOL_DMG="$TOOLS_DIR/dmg"<br /><br /><br />#_______________________________________________________________________________<br />#<br /># Multi-platform tar.gz archive (usable on Linux, Windows, Mac OSX)<br />#_______________________________________________________________________________<br /><br /># Note that al lot of previous variables (Linux, Windows, and Mac OSX specific)<br /># will be used to build this archive<br /><br /># Comment the following line if you don't want to generate multi-platform tar.gz<br /># Note that if ARCH_DEPENDENT is active, this archive will NOT be built<br />OPT_BUILD_MULTI_TARGZ=1<br /><br /># the name of the generated tar.gz<br />TARGZ_NAME=${APP_NAME}-${APP_VERSION}-multiplatform<br /><br /><br />#_______________________________________________________________________________<br /><br />BUILD_CONFIG_INCLUDED=1</pre>
<p>
Pour <strong>utiliser ce script pour votre application</strong>, en raccourci
vous devez remplacer toutes les données du dossier data, images, fichier...
puis ouvrir et adapter le script <code>build_config.sh</code> pour votre appli.
</p>
<p>
<strong>En detail&nbsp;:</strong>
</p>
<ul>
<li>
<p>
remplacer toutes les icônes du dossier <code>data/icons</code>
par les votres.
<br />
Si vous n'avez pas celles aux formats <code>.ico</code> et
<code>.icns</code>, utilisez les scripts <code>build_ico.sh</code> et
<code>build_icns.sh</code> pour les créer. Et utilisez le script
<code>build_base64.sh</code> pour générer l'icône base64 pour le
paquet Maemo.
</p>
</li>
<li>
<p>
Éditez et modifiez le fichier <code>deb_short_license.txt</code>
dans le dossier <code>data/linux</code>.
</p>
</li>
<li>
<p>
Si vous voulez créer un dmg pour Mac OSX et le personnaliser, vous
devez recréer les données utilisées, en particulier le fichier
<code>.DS_STORE</code>, et remplacer celles du dossier
<code>data/mac/dmg_extra_data</code> par les votres.
Faites attention, il y a quelques fichiers cachés dans ce dossier
sur Linux, parce que leur noms commencent par un point (.)
<em>(CTRL+H in Nautilus to show them ;)</em>.
</p>
</li>
<li>
<p>
Assurez vous d'avoir un fichier de licence dans le dossier principal
de vottre appli, c'est nécessaire pour créer l'installeur Windows, et
c'est vraiment une bonne pratique.
</p>
</li>
<li>
<p>
Toutes les autres données peuvent etre utilisées telles quelles,
parce que leurs contenus sont parséx par les scripts et utilise
le fichier de config, mais vous aussi pouvez les éditer et les modifier
si vous le souhaitez.
</p>
</li>
<li>
<p>
Si vous voulez créer un dmg compressé pour Mac OSX, vous devez
télécharger le programme libdmg depuis la
<a href="https://github.com/planetbeing/libdmg-hfsplus" rel="external">page de l'auteur</a>
ou cette <a href="http://shanemcc.co.uk/libdmg/" rel="external">version modifiée</a>,
et le placer dans le dossier <code>tools</code>.
</p>
</li>
<li>
Enfin, éditer et adapter le fichier <strong><code>config.sh</code></strong>
dans le dossier <code>builders</code>.
<br />
Les paramètres les plus importants sont
<code>APP_NAME</code> et <code>APP_DISPLAY_NAME</code>, beaucoup d'autres paramètres
utilisent leurs valeurs.
<br />
Et bien le chemin vers les sources de votre appli, çà peut être une
bonne idée de les placer au même niveau que l'exemple myapp,
mais ce n'est pas obligatoire.
<br />
Remplacer bien sûr toutes les chaînes spécifiques à l'exemple myapp.
</li>
</ul>
<p>Puis dans un terminal&nbsp;:</p>
<ul class="code-xterm">
<li><pre>cd myapp-src-global</pre></li>
<li><pre>sh ./build_all.sh</pre></li>
</ul>
<p>
Et vous trouverez alors dans le dossier <code>myapp-src-all/dist/</code>
tous les installeurs créés.
</p>
</div>
<div class="howto-section">
<h4><span>5.5 Conclusions</span></h4>
<p>
Créer des applications XULRunner est facile, puissant et multi-plateforme,
comme développer des extensions Firefox.
</p>
<p>
Vous pouvez utiliser
<a href="http://www.mozdev.org/projects/wizard/" rel="external">des assistants</a>
sur mozdev.org pour générer des squelettes pour commencer une nouvelle appli
(attention vous devrez adapter
<a href="https://developer.mozilla.org/en/chrome_registration" rel="external">enregistrement chrome</a>
pour Firefox 4, l'assistant a besoin apparemment d'être mis à jour pour cette partie).
</p>
<p>
Nous avons vu dans ce tutoriel quelques petites parties auxquelles nous
devons faire attention pour une meilleure intégration au bureau, et qu'il
est relativement simple de créer des installeurs, depuis Linux, pour différentes
plateformes cibles.
Vous pouvez même réutiliser le script global, ou vous en inspirer, pour
créer ces installeurs pour votre application.
</p>
<p>
Maintenant c'est à vous de faire de jolies applis, j'espère que ce tuto
et le script global vous aideront.
<br />
Amusez vous bien ;) !
</p>
</div>
<div class="howto-navigator-bottom">
<div class="howto-previous"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribuer-votre-appli-XULRunner-4-Mac-OSX" title="Aller au chapitre 4">&lt; chapitre précédent</a></div>
<div class="clearer">&nbsp;</div>
</div>
<div class="howto-author">
<p>Nicolas Martin</p>
</div>
<div class="howto-download-section">
<p>
Vous pouvez télécharger tous les exemples de ce chapitre 5, le script
global et XAL inclus, dans l'archive
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/dl.php?id=current_global" class="howto-download-archive">
myapp-src-global.tar.gz
</a>.
</p>
</div>
<div class="howto-homepage-section">
<p>
Ou retrouver l'intégralité de ce tuto dans
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/" class="howto-homepage-link">
sa page dédiée</a>, disponible en
téléchargement avec tous les exemples compris.
</p>
</div>
<div class="howto-credits">
<p><em>
L'application myapp, de
<a href="https://developer.mozilla.org/en/getting_started_with_xulrunner" rel="external">developer.mozilla.org</a>,
est dans le <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domaine Public</a>.
</em></p>
<p><em>
L'icône utilisée est issue du
<a href="http://tango.freedesktop.org" rel="external">Tango Desktop Project</a>,
et est dans le <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domaine Public</a>.
</em></p>
<p><em>
le lanceur C
<a href="http://joliclic.free.fr/mozilla/xal/en/" rel="external">XUL App Launcher</a> (XAL)
est sous <a href="http://www.opensource.org/licenses/mit-license.php" rel="external">licence MIT</a>.
</em></p>
<p><em>
Toutes les autres données ajoutées, et les fichiers en exemple, de ce chapitre 3, sont dans le
<a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domain Public</a> également.
</em></p>
</div>
<div class="howto-footer">
<p>
Le contenu de cet article est sous les termes de la licence
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>
</p>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width: 0;" src="http://i.creativecommons.org/l/by-sa/3.0/80x15.png" /></a>
</div>
</div>]]></content:encoded>
</item>
     <item rdf:about="http://joliclic.free.fr/blog/index.php?post/2011/05/27/Distribute-your-XULRunner-app-5-Synthesis-all-platforms">
    <title>Distribute your XULRunner app - 5 - Synthesis - all platforms</title>
    <link>http://joliclic.free.fr/blog/index.php?post/2011/05/27/Distribute-your-XULRunner-app-5-Synthesis-all-platforms</link>
    <dc:date>2011-05-27T17:40:00+00:00</dc:date>
    <dc:language>fr</dc:language>
    <dc:creator>Joliclic blog - mozilla</dc:creator>
    <dc:subject></dc:subject>
	<description></description>
	<content:encoded><![CDATA[    <div class="howto">
<p><em>Ce billet existe aussi en <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/Distribuer-votre-appli-XULRunner-5-Synthese-toutes-plateformes">français</a></em></p>
<p><em>
This post is part of a <a href="http://joliclic.free.fr/blog/index.php?tag/dist_xul_app_en">series</a> about how to package a XULRunner application.<br />
See the <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/20/Distribute-your-XULRunner-app-1-Preamble">preamble</a> for the context case.
</em></p>
<h3><span>5 - Synthesis - all platforms</span></h3>
<ul>
<li>5.1 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/#howto_dxr_5.1">Changes to the app</a></li>
<li>5.2 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/#howto_dxr_5.2">Added data</a></li>
<li>5.3 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/#howto_dxr_5.3">Created installers</a></li>
<li>5.4 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/#howto_dxr_5.4">A global and reusable script</a></li>
<li>5.5 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/#howto_dxr_5.5">Conclusions</a></li>
</ul>
<div class="howto-section">
<h4><span>5.1 Changes to the app</span></h4>
<p>
Let summarize the changes we have made to the application itself, for
each platform:
</p>
<ul>
<li>
<h5>Linux</h5>
<ul>
<li>
<p>
We have <strong>added some png icons</strong> into
the <code>myapp/chrome/icons/default/</code> folder.
<br />
This allows to have our icon for our windows and
taskbar.
<br />
In details, 16x16px, 32x32px and 48x48px.
</p>
<p><em>
We can keep this change globally, it will have no impact
on other platforms.
</em></p>
</li>
</ul>
</li>
<li>
<h5>Windows</h5>
<ul>
<li>
<p>
Similarly as for Linux,
we have <strong>added some .ico icon</strong> into
the <code>myapp/chrome/icons/default/</code> folder, for the
same reasons.
<br />
And we have built this icon from Linux with the <code>icotool</code> program.
</p>
<p><em>
We can keep this change globally, it will have no impact
on other platforms.
</em></p>
</li>
</ul>
</li>
<li>
<h5>Mac OSX</h5>
<ul>
<li>
<p>
We have <strong>added a main menubar</strong> in all our
non-modal windows, with <strong>some entries with a special
<code>id</code></strong>.
<br />
This allows to have our owns entries in the Main Menu of Mac.
<br />
These entries are hidden (in XUL sens) by default.
</p>
<p><em>
We can keep this change globally, it will have no impact
on other platforms, because these XUL elements are hidden
for other platforms.
</em></p>
</li>
<li>
<p>
We have <strong>added some JavaScript code</strong> to our main js file,
to allow quitting properly our app. Because on a Mac the app
doesn't quit when we close all windows.
</p>
<p><em>
We can keep this change globally, this code is multi platform.
More, we can use it on the other platform as well.
</em></p>
</li>
<li>
<p>
We have <strong>added a new file, an hidden XUL window</strong>.
This window is used to populate the Main Mac Menu when
all our windows are closed.
</p>
<p><em>
We can keep this change globally, it will have no impact
on other platforms.
</em></p>
</li>
<li>
<p>
And we have <strong>added a new preference</strong>
(<code>browser.hiddenWindowChromeURL</code>),
to use the previous hidden window.
</p>
<p><em>
We can keep this change globally, it will have no impact
on other platforms.
</em></p>
</li>
</ul>
</li>
</ul>
<p>
So, finally these are small changes, and all of them can be added globally,
because they don't disturb the untargeted platforms.
</p>
</div>
<div class="howto-section">
<h4><span>5.2 Added data</span></h4>
<p>
For a better integration to each platforms, we have added some specific data:
</p>
<ul>
<li>
<h5>Linux</h5>
<ul>
<li>
<p>
A <strong>shell script used as launcher</strong>,
which relies on XULRunner or Firefox.
<br />
A symbolic link to this launcher into
<code>/usr/bin/</code> is also created by our
installers.
</p>
</li>
<li>
<p>
A <strong>.desktop file</strong>, for desktop integration,
understood by all main Window Manager.
</p>
</li>
<li>
<p>
And <strong>some icons</strong> (png and svg), used by
the desktop files.
</p>
</li>
</ul>
</li>
<li>
<h5>Windows</h5>
<ul>
<li>
<p>
A <strong>real launcher in C</strong>, in fact
<a href="http://joliclic.free.fr/mozilla/xal/en/" rel="external">XAL</a>
(XUL App Launcher), which allows to easily launch our app
with Firefox, without any black command window, and can
be customized with our icon.
<br />
This launcher can be compiled directly from Linux.
</p>
</li>
<li>
<p>
A batch script as launcher, is possible too, but with
some inherent defaults.
</p>
</li>
</ul>
</li>
<li>
<h5>Mac OSX</h5>
<ul>
<li>
<p>
For this platform, we have in fact encapsulated our app
into a special folder structure with some data,
an <strong>Application Bundle</strong>
</p>
</li>
<li>
<p>
A <strong>shell script used as launcher</strong>, which
uses Firefox (in fact a symbolic link to it, placed in
our bundle)
</p>
</li>
<li>
<p>
A <strong>icns icon</strong>, used by the bundle for the
executable and in the dock.
<br />
And we have built this icon from Linux with the
<code>png2icns</code> program.
</p>
</li>
<li>
<p>
A <strong>Info.plist</strong> file and a
<strong>PkgInfo</strong> file, describing the bundle.
</p>
</li>
</ul>
</li>
</ul>
</div>
<div class="howto-section">
<h4><span>5.3 Created installers</span></h4>
<ul>
<li>
<h5>Multi-platform</h5>
<p>
No real desktop integration, and with some real limitations on Mac,
but a <strong>tar.gz</strong> works and is simple.
</p>
</li>
<li>
<h5>Linux</h5>
<p>
We have created a <strong>deb</strong> package for Debian/Ubuntu
based distributions, a similar deb for <strong>Maemo</strong>,
and a <strong>rpm</strong> for Red Hat/Fedora based distributions.
</p>
</li>
<li>
<h5>Windows</h5>
<p>
We have built a real installer/uninstaller, directly from Linux,
based on <strong>NSIS</strong>.
</p>
</li>
<li>
<h5>Mac OSX</h5>
<p>
The easiest distribution method on Mac, is to create a
<strong>dmg</strong>. We have been able to build it from Linux,
and with an experimental program, to compress it.
</p>
<p>
A simple tar.gz was created too.
</p>
</li>
</ul>
</div>
<div class="howto-section">
<h4><span>5.4 A global and reusable script</span></h4>
<p>
In each chapters, we have used some dedicated bash scripts to create all
our installers and other data.
<br />
I propose now a global script to performs all the tasks in one shot.
</p>
<p>
More, this script can be used with any other XULRunner application, we
only have to adapt a config file.
</p>
<p>
I don't write this script here, you'll find it in the joined archive of
this chapter, but here's the config file:
</p>
<pre>#!/bin/bash<br /><br />#_______________________________________________________________________________<br />#<br /># script version: 1.0<br /># date: 2011-05-20<br />#_______________________________________________________________________________<br /><br /># exit the script on errors<br />set -e<br /><br />#_______________________________________________________________________________<br />#<br /># common configuration<br />#_______________________________________________________________________________<br /><br /># The name of the application, will be the name of the executable for example.<br /># It should contain only [a-zA-Z_-.] and no whitespace.<br />APP_NAME=myapp<br /><br /># The name of the application displayed on screen.<br />APP_DISPLAY_NAME=MyApp<br /><br /># The absolute path to the directory containing this script. Don't modify this<br /># variable if you don't know what you are doing.<br />CUR_DIR=$(dirname "$0")<br />CUR_DIR=$(readlink -f -- "$CUR_DIR")<br /><br /># The main folder of the sources (absolute path), containing the app, data,...<br /># Can be defined before, in some other scripts.<br />if [ ! $MAIN_DIR ]; then<br />    MAIN_DIR=$(readlink -f -- "$CUR_DIR/..")<br />fi<br /><br /># The folder where all resulted builds (installers, archives,...) will be copied<br />DIST_DIR=$MAIN_DIR/dist<br /><br /># The temporary folder where all build are done<br />TMP_DIR=$MAIN_DIR/tmp<br /><br /># Folder which contains extra useful programs for the build script<br />TOOLS_DIR=$MAIN_DIR/tools<br /><br /># Folder which contains all build scripts, and the current config file<br />BUILDERS_DIR=$MAIN_DIR/builders<br /><br /># The folder of the real sources of the XULRunner application<br />APP_SRC_DIR=$MAIN_DIR/$APP_NAME<br /><br /># The folder of the extra data of the app (icons,...)<br />APP_DATA_DIR=$MAIN_DIR/data<br /><br /># The folder of the used icons<br /># This folder must contains:<br /># icon16.png, icon22.png, icon26.png, icon32.png, icon40.png, icon48.png,<br /># icon128.png, icon48.svg, icon.ico, icon.icns, icon48.txt<br /># You can find some shell scripts in the data/icons folder to create the ico,<br /># icns et base64 icons.<br />APP_ICON_DIR=$APP_DATA_DIR/icons<br /><br /># The current version of the app<br />APP_VERSION=1.0<br /><br /># You can use a file named version in the main directory too, and uncomment the<br /># following line to set this variable<br />#APP_VERSION=$(cat "$MAIN_DIR/version")<br /><br /># if the app contains some compiled code, and so it's architecture dependent,<br /># uncomment the following line<br />#ARCH_DEPENDENT=1<br /><br /><br />#_______________________________________________________________________________<br />#<br /># Linux specific<br />#_______________________________________________________________________________<br /><br /># the folder which contains the Linux specifics data<br />LINUX_DIR=$APP_DATA_DIR/linux<br /><br /># the desktop file, will be renamed as $APP_NAME.desktop<br />DESKTOP_FILE=$LINUX_DIR/desktop<br /><br /># If this variable is set, the desktop file will be adapted, i.e. the strings<br /># @@APP_VERSION@@, @@APP_NAME@@, @@APP_DISPLAY_NAME@@, and<br /># @@APP_DESKTOP_CATEGORIE@@,..., will be replaced by their values. Simply<br /># comment the following line to not use this feature.<br />OPT_ADAPT_DESKTOP=1<br /><br /># this value is displayed in a tooltip by the desktop<br />APP_DESKTOP_COMMENT="a Hello World XULRunner app"<br /><br /># A value chosen in http://standards.freedesktop.org/menu-spec/latest/apa.html<br /># If you use multiple value, use a semicolon (;) as separator<br /># DON'T forget the last semicolon, even if there is only one value<br />APP_DESKTOP_CATEGORIE='Utility;'<br /><br /># You can use this variable to put extra lines to the Desktop file, for example<br /># a localized comment<br />APP_DESKTOP_EXTRA='Comment[fr]=un Bonjour Monde pour XULRunner.\n'<br /><br /># the generic Linux launcher, a shell script, for our app. Will be renamed as<br /># $APP_NAME.sh<br />LINUX_LAUNCHER=$LINUX_DIR/launcher.sh<br /><br /><br />#_______________________________________________________________________________<br />#<br /># deb package specific<br />#_______________________________________________________________________________<br /><br /># Comment the following line if you don't want to generate a deb package<br />OPT_BUILD_DEB=1<br /><br /># the debian folder used to build our generic deb<br />DEBIAN_DIR=$APP_DATA_DIR/debian<br /><br /># If this variable is set, the files 'changelog', 'control', 'menu',<br /># 'myapp.link', and 'copyright' of the debian folder will<br /># be adapted, i.e. the strings @@APP_VERSION@@, @@APP_NAME@@,<br /># @@APP_DISPLAY_NAME@@, @@DEB_CONTROL_VERSION@@, @@DEB_CONTROL_SECTION@@,<br /># @@DEB_MENU_SECTION@@, ..., will be replaced by their values. Simply comment<br /># the following line to not use this feature.<br />OPT_ADAPT_DEBIAN=1<br /><br /># The version of the generated deb package.<br />DEB_CONTROL_VERSION=${APP_VERSION}-1<br /><br /># the category of the app. See http://packages.debian.org/en/sid/<br />DEB_CONTROL_SECTION=Utilities<br /><br />DEB_CONTROL_MAINTAINER='John Doe &lt;johndoe@example.com&gt;'<br /><br /># author of the generated deb<br />DEB_CONTROL_AUTHOR=$DEB_CONTROL_MAINTAINER<br /><br />DEB_CONTROL_HOMEPAGE='&lt;http://example.com/myapp/&gt;'<br /><br /># name of the generated package<br />DEB_CONTROL_PACKAGE=$APP_NAME<br /><br /># long description of the app for the generated deb. Can be multiline, see<br /># http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-f-Description<br /># for the formatting (in short, add at least a space at the beginning of all<br /># lines apart the first)<br />DEB_CONTROL_DESCRIPTION='simple Hello World.<br /> Powered by XULRunner.'<br /><br /># if the app have other dependencies than Firefox, list them, separated by a<br /># comma. Important, this list MUST begin by a comma.<br />DEB_CONTROL_EXTRA_DEPENDENCIES=<br /><br /># if the app contains some compiled code, and you want to use the<br /># ${shlibs:Depends} variable with debhelper, uncomment the following line<br />#DEB_CONTROL_USE_SHLIBS_DEPENDS=1<br /><br /># the category for the Debian menu, see<br /># http://www.debian.org/doc/packaging-manuals/menu-policy/ch2.html#s2.1<br />DEB_MENU_SECTION='Applications/Programming'<br /><br />DEB_DATE="$(date -R)"<br /><br />DEB_COPYRIGHT='&lt;Copyright (C) 2010 John Doe&gt;'<br /><br /># the short license for the generated deb<br />DEB_SHORT_LICENSE=$(cat "$LINUX_DIR/deb_short_license.txt")<br /><br /><br />#_______________________________________________________________________________<br />#<br /># maemo deb specific<br />#_______________________________________________________________________________<br /><br /># Note that the debian specific variables are used as well to generate the<br /># maemo deb, so they must set.<br /><br /># the APP_NAME specific for Maemo, can be the same as APP_NAME<br />MOBILE_APP_NAME=$APP_NAME<br /><br /># the APP_DISPLAY_NAME specific for Maemo, can be the same as APP_DISPLAY_NAME<br />MOBILE_APP_DISPLAY_NAME=$APP_DISPLAY_NAME<br /><br /># the name of the app for the package. Should be different than APP_NAME,<br /># otherwise there can be collision with the generic deb created by the other<br /># script<br />MAEMO_PKG_APPNAME=${APP_NAME}-mobile<br /><br /># the desktop file for Maemo, will be renamed as $APP_NAME.desktop<br />MAEMO_DESKTOP_FILE=$LINUX_DIR/maemodesktop<br /><br /># the launcher for Maemo, a shell script, for our app. Will be renamed as<br /># $APP_NAME.sh<br />MAEMO_LAUNCHER=$LINUX_DIR/maemolauncher.sh<br /><br /># Comment the following line if you don't want to generate a deb package<br />OPT_BUILD_MAEMO_DEB=1<br /><br /># the debian folder used to build our deb for Maemo<br />MAEMODEBIAN_DIR=$APP_DATA_DIR/maemodebian<br /><br /># the categorie of the app for Maemo. See<br /># http://wiki.maemo.org/Packaging/Guidelines#Sections<br />DEB_CONTROL_SECTION_MAEMO=user/utilities<br /><br /># the name of the generated deb for Maemo.<br /># Should really the same as MAEMO_PKG_APPNAME, see its comment.<br />DEB_CONTROL_PACKAGE_MAEMO=$MAEMO_PKG_APPNAME<br /><br /># the description of the generated deb, especially for Maemo. See the comments<br /># for DEB_CONTROL_DESCRIPTION in this file for formatting.<br />DEB_CONTROL_DESCRIPTION_MAEMO=$DEB_CONTROL_DESCRIPTION<br /><br /># like DEB_CONTROL_EXTRA_DEPENDENCIES, but for Maemo<br />DEB_CONTROL_EXTRA_DEPENDENCIES_MAEMO=<br /><br /># the base64 file (text) of the icon for the Maemo deb.<br /># Can be generated by the script 'build_icon_base64.sh' in the data/icons dir.<br />MAEMO_BASE64_ICON="$APP_ICON_DIR/icon48.txt"<br /><br /><br />#_______________________________________________________________________________<br />#<br /># rpm package specific<br />#_______________________________________________________________________________<br /><br /># Comment the following line if you don't want to generate a rpm package<br />OPT_BUILD_RPM=1<br /><br /># path to the spec file used to generate the rpm<br />RPM_SPEC_FILE=$LINUX_DIR/rpmspec<br /><br /># If this variable is set, the .spec file will<br /># be adapted, i.e. the strings @@APP_VERSION@@, @@APP_NAME@@,<br /># @@APP_DISPLAY_NAME@@, @@RPM_VERSION@@, @@RPM_RELEASE@@, @@RPM_GROUP@@,<br /># @@RPM_LICENSE@@, @@RPM_URL@@, @@RPM_SOURCE@@, @@RPM_DATE@@, ...<br /># will be replaced by their values. Simply comment the following line to not use<br /># this feature.<br />OPT_ADAPT_RPM=1<br /><br /># version of the app for the spec file: must contain only integer and digit, no<br /># strings like 'beta'<br />RPM_VERSION=$APP_VERSION<br /><br /># the version of the generated rpm, not the app version<br />RPM_RELEASE='1%{?dist}'<br /><br /># the short version of the generated rpm, without any string relative to the<br /># distribution or architecture<br />#RPM_RELEASE_SHORT=1<br />RPM_RELEASE_SHORT=$(echo $RPM_RELEASE | sed "s/%.*$//")<br /><br /># breve summary of the app for the package. One line only.<br />RPM_SUMMARY='simple Hello World powered by XULRunner.'<br /><br /># the category of the app. See /usr/share/doc/rpm/GROUPS<br />RPM_GROUP=Development/Tools<br /><br /># keyword license<br />RPM_LICENSE='MPLv1.1 or GPLv2+ or LGPLv2+'<br /><br /># url where the source of our app can be found<br />RPM_URL='http://example.com/myapp/'<br /><br /># the name of the dummy tar.gz source archive, it will be built by this script.<br />RPM_SOURCE=${APP_NAME}-${RPM_VERSION}.tar.gz<br /><br /># If the app need some build dependencies, uncomment the following line and add<br /># them here, separated by a comma. BUT you shouldn't have to, the logic here is<br /># that the built should have been done before, this script simply package the<br /># result.<br />#RPM_BUILDREQUIRES=<br /><br /># if the app have other dependencies than Firefox, list them, separated by a<br /># comma. Important, this list MUST begin by a comma.<br />RPM_EXTRA_REQUIRES=<br /><br /># long description of the app for the generated rpm. Can be multiline.<br />RPM_DESCRIPTION='simple Hello World<br />Powered by XULRunner.'<br /><br />LC_TIME_BUFFER=$LC_TIME<br />export LC_TIME="en_EN.utf8"<br />RPM_DATE=$(date +"%a %b %e %Y")<br />export LC_TIME="$LC_TIME_BUFFER"<br /><br />RPM_MAINTAINER='John Doe &lt;johndoe@example.com&gt;'<br /><br /><br />#_______________________________________________________________________________<br />#<br /># Windows specific<br />#_______________________________________________________________________________<br /><br /># the folder which contains the Windows specifics data<br />WIN_DIR=$APP_DATA_DIR/win<br /><br /># the version of the app used by some other variables. String.<br />WIN_VERSION=$APP_VERSION<br /><br /># comment this line if you don't want to build xal, the launcher in C<br />OPT_BUILD_WIN_XAL=1<br /><br /># source directory of xal<br />XAL_SRC_DIR=$TOOLS_DIR/xal-src<br /><br /># the rc file used to build xal<br />WIN_RESOURCE=$WIN_DIR/resource.rc<br /><br /># If this variable is set, the resource (.rc) file for xal will<br /># be adapted, i.e. the strings @@APP_VERSION@@, @@APP_NAME@@,<br /># @@APP_DISPLAY_NAME@@, and @@WINRES_...@@<br /># will be replaced by their values. Simply comment the following line to not use<br /># this feature.<br />OPT_ADAPT_WINRES=1<br /><br />WINRES_FILEVERSION='0,1,0,0'<br /># the FILEVERSION for Windows (&lt;int,int,int,int&gt;) will be deducted from the<br /># APP_VERSION. Comment this line if you don't want use this feature<br />OPT_CALC_WINRES_FVERSION=1<br /><br />WINRES_PRODUCTVERSION='0,1,0,0'<br /># the PRODUCTVERSION for Windows (&lt;int,int,int,int&gt;) will be deducted from the<br /># APP_VERSION. Comment this line if you don't want use this feature<br />OPT_CALC_WINRES_PVERSION=1<br /><br />WINRES_Comments='Published under the MPL 1.1/GPL 2.0/LGPL 2.1 licenses'<br />WINRES_CompanyName='John Doe Organization'<br />WINRES_FileDescription=$APP_DISPLAY_NAME<br />WINRES_FileVersion=$WIN_VERSION<br />WINRES_InternalName=$APP_NAME<br />WINRES_LegalCopyright='(c) 2010 John Doe'<br />WINRES_ProductName=$APP_DISPLAY_NAME<br />WINRES_ProductVersion=$WIN_VERSION<br /><br /># Comment the following line if you don't want to generate the nsis installer<br /># for Windows<br />OPT_BUILD_WIN_INSTALLER=1<br /><br /># the source folder of the nsis scripts used by this script<br />NSIS_SRC_DIR=$APP_DATA_DIR/nsis<br /><br /># If this variable is set, the nsis script will<br /># be adapted, i.e. the strings @@APP_VERSION@@, @@APP_NAME@@,<br /># @@APP_DISPLAY_NAME@@, and @@NSIS_...@@<br /># will be replaced by their values. Simply comment the following line to not use<br /># this feature.<br />OPT_ADAPT_NSIS=1<br /><br />NSIS_PRODUCT_NAME=$APP_DISPLAY_NAME<br />NSIS_PRODUCT_INTERNAL_NAME=$APP_NAME<br />NSIS_PRODUCT_VERSION=$WIN_VERSION<br />NSIS_PRODUCT_WIN_VERSION='1.0.0.0'<br /># for nsis, the PRODUCTVERSION for Windows (&lt;int,int,int,int&gt;) will be deducted<br /># from the APP_VERSION. Comment this line if you don't want use this feature<br />OPT_CALC_NSIS_WINVERSION=1<br /><br /># The license file text MUST be in the main root app folder, so in $APP_SRC_DIR.<br /># Otherwise, you can edit the nsis script and adapt it<br />NSIS_LICENCE_NAME='LICENSE.txt'<br /><br /># the name of the generated nsis installer<br />NSIS_INSTALLER_NAME="$APP_DISPLAY_NAME-$APP_VERSION-install.exe"<br /><br /><br />#_______________________________________________________________________________<br />#<br /># Mac OSX specific<br />#_______________________________________________________________________________<br /><br /># the folder which contains the Mac OSX specifics data<br />MAC_DIR=$APP_DATA_DIR/mac<br /><br /># the simple and basic shell launcher for Mac. Used only for the<br /># multiplatform tar.gz<br />MAC_BASIC_LAUNCHER=$MAC_DIR/basic_launcher.sh<br /><br /># the previous basic launcher will be renamed with this value<br /># Trick: if the extension is 'command', the file can double-clicked in the Mac<br /># Finder, then a terminal will be opened and the script will be launched.<br />MAC_BASIC_LAUNCHER_NAME=${APP_NAME}-mac.command<br /><br /># Comment the following line if you don't want to generate the Application<br /># Bundle of the app for Mac.<br />OPT_BUILD_MAC_BUNDLE=1<br /><br /># path to the used skeleton of the bundle<br />DMG_SKELET_DIR=$MAC_DIR/bundle_skelet<br /><br /># If this variable is set, the nsis script will<br /># be adapted, i.e. the strings @@APP_VERSION@@, @@APP_NAME@@,<br /># @@APP_DISPLAY_NAME@@, and @@MAC_...@@<br /># will be replaced by their values. Simply comment the following line to not use<br /># this feature.<br />OPT_ADAPT_MAC_INFO=1<br /><br />MAC_BUNDLE_EXECUTABLE=${APP_NAME}-mac.sh<br />MAC_BUNDLE_INFOSTRING="$APP_DISPLAY_NAME $APP_VERSION"<br />MAC_BUNDLE_ICONFILE=$APP_NAME<br />MAC_BUNDLE_IDENTIFIER="net.yourcompany.${APP_NAME}"<br />MAC_BUNDLE_NAME=$APP_DISPLAY_NAME<br />MAC_BUNDLE_SHORTVERSIONSTRING=$APP_VERSION<br />MAC_BUNDLE_VERSION=$APP_VERSION<br /><br /># with this option, the eventual icon 'myapp.icns' in the Contents/Resources<br /># folder of the used bundle skelet will be removed, and the icns icon of the<br /># icons folder will be added to the bundle renamed as MAC_BUNDLE_ICONFILE<br />MAC_BUNDLE_OVERWRITE_ICON=1<br /><br /># comment the following line if you don't want to generate a dmg image <br />OPT_BUILD_MAC_DMG=1<br /># comment the following line if you don't want to customize the dmg image <br />OPT_CUSTOMIZE_DMG=1<br /># source folder of the data added to the dmg, to customize it<br /># Note that you have to recreate manually these customizations files if the<br /># DMG_VOLNAME is different than 'MyApp', in particular the background image<br /># will not be displayed. See the Howto.<br /># Comment the line to disabled this option.<br />DMG_CUSTOM_DATA_DIR=$MAC_DIR/dmg_extra_data<br /><br /># the name of the mounted dmg disk image<br />DMG_VOLNAME="$APP_DISPLAY_NAME"<br /># the name of the generated dmg<br />DMG_NAME="$APP_NAME-$APP_VERSION.dmg"<br /><br /># comment the following line if you don't want to compress the dmg. You need<br /># the &lt;dmg&gt; program to be able to do that<br />OPT_COMPRESS_DMG=1<br /># path to the dmg program, used to compress the dmg.<br /># see http://github.com/planetbeing/libdmg-hfsplus<br /># and http://shanemcc.co.uk/libdmg/<br />TOOL_DMG="$TOOLS_DIR/dmg"<br /><br /><br />#_______________________________________________________________________________<br />#<br /># Multi-platform tar.gz archive (usable on Linux, Windows, Mac OSX)<br />#_______________________________________________________________________________<br /><br /># Note that al lot of previous variables (Linux, Windows, and Mac OSX specific)<br /># will be used to build this archive<br /><br /># Comment the following line if you don't want to generate multi-platform tar.gz<br /># Note that if ARCH_DEPENDENT is active, this archive will NOT be built<br />OPT_BUILD_MULTI_TARGZ=1<br /><br /># the name of the generated tar.gz<br />TARGZ_NAME=${APP_NAME}-${APP_VERSION}-multiplatform<br /><br /><br />#_______________________________________________________________________________<br /><br />BUILD_CONFIG_INCLUDED=1</pre>
<p>
To <strong>use this script for your own application</strong>, in short
you  have to overwrite all data included in the data folder, image,
files... then open and adapt the <code>build_config.sh</code> script to
your own.
</p>
<p>
<strong>In detail:</strong>
</p>
<ul>
<li>
<p>
replace all icons in the <code>data/icons</code> folder by your owns.
<br />
If you don't have the <code>.ico</code> and <code>.icns</code>
ones, use the scripts <code>build_ico.sh</code> and
<code>build_icns.sh</code> to build them. And use the
<code>build_base64.sh</code> script to generate the base64 icon
for the Maemo package.
</p>
</li>
<li>
<p>
Edit and modify the file <code>deb_short_license.txt</code> in
the <code>data/linux</code> folder.
</p>
</li>
<li>
<p>
If you want to create a dmg for Mac OSX and customize it, you should
recreate the used data, in particular the <code>.DS_STORE</code> file,
and overwrite them in the <code>data/mac/dmg_extra_data</code>
folder. Be careful, there're some hidden files in this folder on Linux,
because their names begin with a dot (.)
<em>(CTRL+H in Nautilus to show them ;)</em>.
</p>
</li>
<li>
<p>
Be sure to have a license file into the main folder of your app, this
is required  to build the Windows installer, and this is really a good
practice.
</p>
</li>
<li>
<p>
All other data could be used as is, because their contents will
parsed by the scripts and use the config file, but you can edit
and change them as well.
</p>
</li>
<li>
<p>
If you want to create a compressed dmg for Mac OSX, you have to
download the libdmg program from the
<a href="https://github.com/planetbeing/libdmg-hfsplus" rel="external">author page</a>
or this <a href="http://shanemcc.co.uk/libdmg/" rel="external">modified version</a>,
and place it in the <code>tools</code> folder.
</p>
</li>
<li>
Finally, edit and adapt the <strong><code>config.sh</code></strong>
file in the <code>builders</code> folder.
<br />
The most important parameters
are <code>APP_NAME</code> and <code>APP_DISPLAY_NAME</code>, a lot of
others parameters use them.
<br />
And of course the path to the sources of your app,
it could be a good idea to place them at the same level of the myapp
example, but that's not required.
<br />
Replace of course all strings specifics to the myapp example.
</li>
</ul>
<p>Then, in a terminal:</p>
<ul class="code-xterm">
<li><pre>cd myapp-src-global</pre></li>
<li><pre>sh ./build_all.sh</pre></li>
</ul>
<p>
And you will find into the <code>myapp-src-all/dist/</code> folder all
the created installers.
</p>
</div>
<div class="howto-section">
<h4><span>5.5 Conclusions</span></h4>
<p>
Creating XULRunner applications is easy, powerful, and multiplatform,
like developing Firefox extensions.
</p>
<p>
You can use <a href="http://www.mozdev.org/projects/wizard/" rel="external">some wizards</a>
from mozdev.org to generate a skeleton to begin a new app (be careful,
you will have to adapt the
<a href="https://developer.mozilla.org/en/chrome_registration" rel="external">chrome registration</a>
for Firefox 4, the wizard need apparently to be updated for this part).
</p>
<p>
We have seen in this how-to some small parts that we need to taking care
for a better desktop integration, and that it is relatively easy to
create installers, from Linux, for several platforms. You can even reuse
the global script, or get inspiration from it, to create these installers
for your own application.
</p>
<p>
Now it's up to you to make some nice apps, I hope this how-to and the
global script will help you.
<br />
Have fun ;) !
</p>
</div>
<div class="howto-navigator-bottom">
<div class="howto-previous"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribute-your-XULRunner-app-4-Mac-OSX" title="Go to chapter 4">&lt; previous chapter</a></div>
<div class="clearer">&nbsp;</div>
</div>
<div class="howto-author">
<p>Nicolas Martin</p>
</div>
<div class="howto-download-section">
<p>
You can download all the samples of this chapter 5, the global script
and XAL included, in the
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/dl.php?id=current_global" class="howto-download-archive">myapp-src-global.tar.gz</a>
archive.
</p>
</div>
<div class="howto-homepage-section">
<p>
Or retrieve this entire how-to in its
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/en/" class="howto-homepage-link">
dedicated page</a>,
downloadable with all the examples.
</p>
</div>
<div class="howto-credits">
<p><em>
The myapp application, from
<a href="https://developer.mozilla.org/en/getting_started_with_xulrunner" rel="external">developer.mozilla.org</a>
is in the <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a>.
</em></p>
<p><em>
The icon used is from the
<a href="http://tango.freedesktop.org" rel="external">Tango Desktop Project</a>,
and is in the <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a>.
</em></p>
<p><em>
The C launcher
<a href="http://joliclic.free.fr/mozilla/xal/en/" rel="external">XUL App Launcher</a> (XAL)
is under the <a href="http://www.opensource.org/licenses/mit-license.php" rel="external">MIT license</a>.
</em></p>
<p><em>
All other added data, and sample files, of this chapter 5, are under
<a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a>s too.
</em></p>
</div>
<div class="howto-footer">
<p>
The content of this article
is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>
</p>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width: 0;" src="http://i.creativecommons.org/l/by-sa/3.0/80x15.png" /></a>
</div>
</div>]]></content:encoded>
</item>
     <item rdf:about="http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribuer-votre-appli-XULRunner-4-Mac-OSX">
    <title>Distribuer votre appli XULRunner - 4 - Mac OSX</title>
    <link>http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribuer-votre-appli-XULRunner-4-Mac-OSX</link>
    <dc:date>2011-05-26T15:00:00+00:00</dc:date>
    <dc:language>fr</dc:language>
    <dc:creator>Joliclic blog - mozilla</dc:creator>
    <dc:subject></dc:subject>
	<description></description>
	<content:encoded><![CDATA[    <div class="howto">
<p><em>This post exists also in <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribute-your-XULRunner-app-4-Mac-OSX">english</a></em></p>
<p><em>
Ce billet fait partie d'une <a href="http://joliclic.free.fr/blog/index.php?tag/dist_xul_app_fr">série</a> sur comment déployer une application XULRunner.
Voir le <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/20/Distribuer-votre-appli-XULRunner-1-Preambule">préambule</a> pour le contexte.
</em></p>
<h3><span>4 - Mac OSX</span></h3>
<ul>
<li>4.1 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/#howtofr_dxr_4.1">Icônes pour Mac OSX</a></li>
<li>4.2 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/#howtofr_dxr_4.2">Créer un lanceur</a></li>
<li>4.3 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/#howtofr_dxr_4.3">Quelques spécifités Mac</a></li>
<li>4.4 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/#howtofr_dxr_4.4">Créer un "Application Bundle"</a></li>
<li>4.5 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/#howtofr_dxr_4.5">Empaqueter un tar.gz et un dmg</a></li>
</ul>
<div class="howto-section">
<h4><span>4.1 Icônes pour Mac OSX</span></h4>
<p>
Nous avons besoin d'une icône
<strong><a href="http://en.wikipedia.org/wiki/Icns" rel="external">icns</a></strong>
Sur Mac les fenêtres n'ont pas d'icône, mais, plus tard, nous en utiliserons
une dans le Dock. Et elle sera utilisée pour le bundle que nous créerons.
</p>
<p>
Nous pouvons générer ce fichier <code>.icns</code> directement depuis
Linux. La restriction est que nous ne pouvons pas inclure des images avec
pluieurs profondeur de couleur, mais des dimensions multiples est possible.
<br />
Nous avons besoin du programme <code>png2icns</code> compris dans le
paquet <strong>icnsutils</strong>.
<br />
Sur Debian/Ubuntu:
</p>
<p><code class="code-xterm-root">apt_get install icnsutils</code></p>
<p>Nous obtenoons notre fichier icns à partir de plusieurs png avec&nbsp;:</p>
<p><kbd class="code-xterm">png2icns icon.icns icon128.png icon48.png icon32.png icon16.png</kbd></p>
<p><em>
Vous trouverez un script bash avec cette ligne de commande dans l'archive
d'exemple relative à ce chapitre 4
(dans <code>samples_chapter_4/data/icons/</code>).
</em></p>
</div>
<div class="howto-section">
<h4><span>4.2 Créer un lanceur</span></h4>
<p>
Comme pour Linux, nous utiliserons un <strong>script shell</strong>
pour notre <strong>lanceur</strong>.
Mais nous avons plusieurs problèmes à résoudre.
</p>
<p>
le premier n'est pas trop difficile. Le programme <code>readlink</code>
disponible sur Mac OSX n'est pas la version GNU, et nous ne pouvons pas
utiliser l'option <code>-f</code>. Nous résouderons nous même cette fonctionnalité.
</p>
<p>
Un problème plus sérieux, est que <em>nous ne pouvons pas déterminer où
Firefox est installé</em>. Donc, ici, nous imposerons une limitation,
<em>Firefox <strong>doit</strong> être installer à son emplacement par défaut</em>,
c'est à dire <code>/Applications/</code> .
</p>
<p><em>
Note&nbsp;: si vous une suggestions pour déterminer où est installer Firefox,
merci de me le faire savoir ;) .
</em></p>
<p>
Voici ce script, <code><strong>myapp-mac.sh</strong></code>, bien que ce ne soit
pas exactement celui que nous utiliserons plus tard&nbsp;:
</p>
<pre>#!/bin/sh<br /><br />set -e<br /><br /># see http://stackoverflow.com/questions/7665/how-to-resolve-symbolic-links-in-a-shell-script<br /># get the absolute path of the executable<br />SELF_PATH=$(cd -P -- "$(dirname -- "$0")" &amp;&amp; \<br />    pwd -P) &amp;&amp; SELF_PATH=$SELF_PATH/$(basename -- "$0")<br /><br /># resolve symlinks<br />while [ -h $SELF_PATH ]; do<br />    DIR=$(dirname -- "$SELF_PATH")<br />    SYM=$(readlink $SELF_PATH)<br />    SELF_PATH=$(cd $DIR &amp;&amp; cd $(dirname -- "$SYM") &amp;&amp; pwd)/$(basename -- "$SYM")<br />done<br /><br />CUR_DIR=$(dirname "$SELF_PATH")<br /><br />if [ -x /Applications/Firefox.app/Contents/MacOS/firefox-bin ]; then<br />    /Applications/Firefox.app/Contents/MacOS/firefox-bin -app "$CUR_DIR/application.ini" $@<br />elif [ -x /Library/Frameworks/XUL.framework/xulrunner-bin ]; then<br />    /Library/Frameworks/XUL.framework/xulrunner-bin "$CUR_DIR/application.ini" $@<br />else<br />    echo "Error: unable to find Firefox or XULRunner!"<br />fi</pre>
<p>
Si nous essayons ce lanceur, nous pouvons voir 2 autres problèmes,
l'icône affichée dans le dock est celui de Firefox, et le menu principal,
quand nous fermons toutes les fenêtres de notre appli, est celui de Firefox.
<br />
il y a des solutions à ces problèmes, comme nous le verrons dans les prochaines
parties.
</p>
<p>
<em>Notez que si vous voulez vraiment utiliser un tel script, sans un bundle,
vous pouvez vouloir l'utiliser avec l'extension <code>.command</code>
plutôt que <code>.sh</code>, car alors le fichier peut être double-cliqué
dans le Finder de Mac, ce qui ouvrira un terminal, puis l'appli.</em>
</p>
</div>
<div class="howto-section">
<h4><span>4.3 Quelques spécifités Mac</span></h4>
<p>
Une particularité sur Mac, est le <strong>Menu principal</strong>
contrôler par le système d'exploitation, et correspondant à l'application
courante qui a le focus. Et quand toutes les fenêtres d'une même application
sont fermées, ce menu reste présent tant que l'on ne quitte pas l'application;
</p>
<p>
Ceci est bien pris en charge dans une application XULRunner, mais nous
devons ajouter un peu de code pour celà.
</p>
<p>Quelques docuementation sur MDN:</p>
<ul>
<li>
<a rel="external" href="https://developer.mozilla.org/en/XUL_School/Adding_menus_and_submenus#Menus_on_Mac_OS_X">Menus on Mac OS X</a>
</li>
<li>
<a rel="external" href="https://developer.mozilla.org/en/XULRunner/MacFAQ#UI_notes">MacFAQ: UI_notes</a>
</li>
</ul>
<p>
Si notre appli utilises un élément <code>menubar</code> principal, XULRunner/Firefox
l'utilisera (en fait le premier menubar) pour créer ce menu spécial. Si vous n'en
avez pas, vous devriez en créer un, masquer par défaut pour les autres plateformes,
il permettra la construction de ce menu.
</p>
<p>
les entrées dans le menu "pomme" sont construits d'après des éléments avec
des <code>id</code> réservés. Vous devriez créer au moins quelques entrées,
pour permettre de quitter l'appli par exemple.
</p>
<p>
Voici la liste des id disponibles correspondants à ces entrées
(<a rel="external" href="http://mxr.mozilla.org/mozilla1.9.2/source/widget/src/cocoa/nsMenuBarX.mm#564">sources</a>)&nbsp;:
</p>
<table>
<thead>
<tr>
<th>id de l'élément</th>
<th>item du menu correspondant</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>aboutName</code></td>
<td>À propos de cette application</td>
</tr>
<tr>
<td><code>menu_preferences</code></td>
<td>Préférences...</td>
</tr>
<tr>
<td><code>menu_mac_services</code></td>
<td>Services</td>
</tr>
<tr>
<td><code>menu_mac_hide_app</code></td>
<td>Masquer l'appli</td>
</tr>
<tr>
<td><code>menu_mac_hide_others</code></td>
<td>Masquer les autres</td>
</tr>
<tr>
<td><code>menu_mac_show_all</code></td>
<td>Tout afficher</td>
</tr>
<tr>
<td><code>menu_FileQuitItem</code></td>
<td>Quitter</td>
</tr>
</tbody>
</table>
<p>
et voici un exemple d'un menu xul minimal pour cet usage&nbsp;:
</p>
<pre>  &lt;commandset id="main-commands"&gt;<br />      &lt;command id="cmd:quit" oncommand="myappQuitApplication();"/&gt;<br />  &lt;/commandset&gt;<br />  <br />  &lt;keyset id="ui-keys"&gt;<br />      &lt;key id="key:quitApp" key="Q" modifiers="accel" command="cmd:quit"/&gt;<br />      &lt;key id="key:hideApp" key="H" modifiers="accel"/&gt;<br />      &lt;key id="key:hideOthersApp" key="H" modifiers="accel,alt"/&gt;<br />  &lt;/keyset&gt;<br />  <br />  &lt;menubar id="main-menubar" hidden="true"&gt;<br />      &lt;menu id="mac-menu"&gt;<br />          &lt;menupopup&gt;<br />              &lt;menuitem id="menu_mac_hide_app" label="Hide My App" key="key:hideApp"/&gt;<br />              &lt;menuitem id="menu_mac_hide_others" label="Hide Others" key="key:hideOthersApp"/&gt;<br />              &lt;menuitem id="menu_mac_show_all" label="Show All"/&gt;<br />              &lt;menuitem id="menu_FileQuitItem" label="Quit" key="key:quitApp" command="cmd:quit"/&gt;<br />          &lt;/menupopup&gt;<br />      &lt;/menu&gt;<br />  &lt;/menubar&gt;</pre>
<p>
Bien sur, comme pour les autres parties de l'appli, les chaînes utilisées
dans les labels et clés
<a rel="external" href="https://developer.mozilla.org/en/Localization"><strong>devraient être localisées</strong></a>.
Mais ce n'est pas le propos de ce tutoriel.
</p>
<p>
La fonction <code>myappQuitApplication</code> a été ajoutée dans le fichier
<code>main.js</code> de notre appli&nbsp;:
</p>
<pre>function myappQuitApplication() {<br />  const Cc = Components.classes;<br />  const Ci = Components.interfaces;<br />    <br />  let appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].<br />                   getService(Ci.nsIAppStartup);<br />  appStartup.quit(Ci.nsIAppStartup.eAttemptQuit);<br />  <br />  return true;<br />}</pre>
<p>
Enfin, le dernier problème&nbsp;: quand toutes les fenêtres de notre
appli sont fermées, en fait l'appli ne quitte pas, et le menu principal
demeure. Plus, tel quel, c'est le menu de Firefox que nous voyons.
<br />
En fait, il y a une fenêtre speciale et cachée que XULRunner utilises pour ce menu.
Donc nous devons créer une telle fenêtre, et définir une préférence pour
la spécifier.
</p>
<p>Voilà la préférence ajoutée dans <code>defaults/preferences/pref.js</code>&nbsp;:</p>
<pre>pref("browser.hiddenWindowChromeURL", "chrome://myapp/content/hiddenWindow.xul");</pre>
<p>Et le contenu de  <code>hiddenWindow.xul</code>, qui contient uniquement notre menubar&nbsp;:</p>
<pre>&lt;window id="hiddenWindow"<br />        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"&gt;<br />    &lt;script type="application/javascript"&gt;<br />    &lt;![CDATA[<br />function myappQuitApplication() {<br />    const Cc = Components.classes;<br />    const Ci = Components.interfaces;<br />    <br />    let appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].<br />                     getService(Ci.nsIAppStartup);<br />    appStartup.quit(Ci.nsIAppStartup.eAttemptQuit);<br />    <br />    return true;<br />}<br />    ]]&gt;<br />    &lt;/script&gt;<br />  <br />    &lt;commandset id="main-commands"&gt;<br />        &lt;command id="cmd:quit" oncommand="myappQuitApplication();"/&gt;<br />    &lt;/commandset&gt;<br />    <br />    &lt;keyset id="ui-keys"&gt;<br />        &lt;key id="key:quitApp" key="Q" modifiers="accel" command="cmd:quit"/&gt;<br />        &lt;key id="key:hideApp" key="H" modifiers="accel"/&gt;<br />        &lt;key id="key:hideOthersApp" key="H" modifiers="accel,alt"/&gt;<br />    &lt;/keyset&gt;<br />    <br />    &lt;menubar id="main-menubar" hidden="true"&gt;<br />        &lt;menu id="mac-menu"&gt;<br />            &lt;menupopup&gt;<br />                &lt;menuitem id="menu_mac_hide_app" label="Hide My App" key="key:hideApp"/&gt;<br />                &lt;menuitem id="menu_mac_hide_others" label="Hide Others" key="key:hideOthersApp"/&gt;<br />                &lt;menuitem id="menu_mac_show_all" label="Show All"/&gt;<br />                &lt;menuitem id="menu_FileQuitItem" label="Quit" key="key:quitApp" command="cmd:quit"/&gt;<br />            &lt;/menupopup&gt;<br />        &lt;/menu&gt;<br />    &lt;/menubar&gt;<br />&lt;/window&gt;</pre>
</div>
<div class="howto-section">
<h4><span>4.4 Créer un "Application Bundle"</span></h4>
<p>
Sur Mac OSX, les applications sont empaquetées dans un format spécial
nommé <strong>Application Bundle</strong>. C'est en fait un dossier, nommé
avec l'extension <code>.app</code>, et avec une structure particulière.
</p>
<p>Quelques documentations utiles&nbsp;:</p>
<ul>
<li><a rel="external" href="http://www.mactipsandtricks.com/articles/Wiley_HT_appBundles2.lasso">Inside Application Bundles</a></li>
<li><a rel="external" href="http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPRuntimeConfig/000-Introduction/introduction.html">Runtime Configuration Guidelines: Introduction</a></li>
<li><a rel="external" href="https://developer.mozilla.org/en/XULRunner/Creating_custom_app_bundles_for_Mac_OS_X">Custom app bundles for Mac OS X</a></li>
</ul>
<p>Voici une proposition d'un dossier <code>.app</code> pour notre appli&nbsp;:</p>
<pre>    |- MyApp.app/<br />        |- Contents/<br />            |- MacOS/<br />                |- chrome/<br />                |- defaults/<br />                |- application.ini<br />                |- chrome.manifest<br />                |- foxstub<br />                |- myapp-mac.sh<br />            |- Resources/<br />                |- myapp.icns<br />            |- Info.plist<br />            |- PkgInfo</pre>
<p>
le dossier <code><strong>MacOS</strong></code> contient en fait tous les fichiers
et dossiers de notre appli XULRunner.
</p>
<p>
le dossier <code><strong>Resources</strong></code> contient uniquement notre
icône au format icns.
</p>
<p>
Le fichier <code><strong>PkgInfo</strong></code> contient uniquement la chaîne
<code>APPL????</code>. Je ne suis pas sûr que ce fichier soit réellement nécessaire,
il semble important pour la compatibilité avec Mac OS 9.
<br />
La valeur spécifie que ce bundle est une application, et comme nous n'avons
pas d'identifiant de 4 caractères valide, nous utilisons 4 points d'interrogation
(<code>????</code>).
</p>
<p>
Le fichier <code><strong>Info.plist</strong></code> décrit notre appli&nbsp;:
</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;<br />&lt;plist version="1.0"&gt;<br />&lt;dict&gt;<br />	&lt;key&gt;CFBundleDevelopmentRegion&lt;/key&gt;<br />	&lt;string&gt;English&lt;/string&gt;<br />	&lt;key&gt;CFBundleExecutable&lt;/key&gt;<br />	&lt;string&gt;myapp-mac.sh&lt;/string&gt;<br />	&lt;key&gt;CFBundleGetInfoString&lt;/key&gt;<br />	&lt;string&gt;MyApp 1.0&lt;/string&gt;<br />	&lt;key&gt;CFBundleIconFile&lt;/key&gt;<br />	&lt;string&gt;myapp&lt;/string&gt;<br />	&lt;key&gt;CFBundleIdentifier&lt;/key&gt;<br />	&lt;string&gt;net.yourcompany.myapp&lt;/string&gt;<br />	&lt;key&gt;CFBundleInfoDictionaryVersion&lt;/key&gt;<br />	&lt;string&gt;6.0&lt;/string&gt;<br />	&lt;key&gt;CFBundleName&lt;/key&gt;<br />	&lt;string&gt;MyApp&lt;/string&gt;<br />	&lt;key&gt;CFBundlePackageType&lt;/key&gt;<br />	&lt;string&gt;APPL&lt;/string&gt;<br />	&lt;key&gt;CFBundleShortVersionString&lt;/key&gt;<br />	&lt;string&gt;1.0.0.0&lt;/string&gt;<br />	&lt;key&gt;CFBundleSignature&lt;/key&gt;<br />	&lt;string&gt;????&lt;/string&gt;<br />	&lt;key&gt;CFBundleVersion&lt;/key&gt;<br />	&lt;string&gt;1.0.0.0&lt;/string&gt;<br />	&lt;key&gt;NSAppleScriptEnabled&lt;/key&gt;<br />	&lt;true/&gt;<br />&lt;/dict&gt;<br />&lt;/plist&gt;</pre>
<p>Quelques commentaires sur ces propriétés&nbsp;:</p>
<p>
<code><strong>CFBundleExecutable</strong></code> pointe sur notre lanceur,
le script  shell nommé <code>myapp-mac.sh</code>.
</p>
<p>
la valeur de <code><strong>CFBundleIconFile</strong></code> est
<code>myapp</code> parce que notre icône dans le dossier Resources est nommée
<code><strong>myapp</strong>.icns</code>. Maintenant, l'utilisateur final
visualise notre bundle avec notre icône.
</p>
<p>
<code><strong>CFBundleIdentifier</strong></code> est formaté tel que
<code>domaine inversé point nom de l'application</code>. Ce doit être un
identifiant unique pour notre appli.
</p>
<p>
<code><strong>CFBundlePackageType</strong></code> spécifie que c'est un
"application bundle" (<code>APPL</code>).
</p>
<p>
La valeur de <code><strong>CFBundleSignature</strong></code> est
<code>????</code> parce que nous n'avons pas de signature. C'est supposé
être un identifiant unique de 4 caractères, et supposé être obtenue
après un enregistrement auprès d'Apple. Tel que je le comprend, c'est
exiger essentiellement pour Mac OS 9. Ne vous inquiétez pas, je n'ai pas
vu de problème avec cette valeur ;) .
</p>
<p>
Maintenant voyons <strong>une belle astuce</strong>. Tel quel, l'utilisateur
final voit notre appli avec notre icône, mais quand il la lance, l'icône
dans le dock est celle de Firefox.
<br />
Dans l'arborescence du dossier de notre bundle, vous pouvez voir un fichier
nommé <code><strong>foxstub</strong></code>, ce fichier est en fait un
<strong>lien symbolique vers l'exécutable de Firefox</strong>.
</p>
<p>Ce lien est obtenu simplement, dans le dossier MacOS, avec&nbsp;:</p>
<p>
<kbd class="code-xterm">ln -s /Applications/Firefox.app/Contents/MacOS/firefox-bin foxstub</kbd>
</p>
<p>
Maintenant quand l'utilisateur lance notre appli, c'est bien notre icône
qui est affichée dans le dock :) .
</p>
<p><em>
En fait, notre icône apparait dans le dock, puis disparait, et réapparait
de nouveau, parce que notre script est lancé, puis l'exécutable lié. mais ce
n'est pas un gros problème.
</em></p>
<p>
Voici le script modifié de notre lanceur <code>myapp-mac.sh</code>, qui
utilise dorénavant le lien symbolique vers Firefox&nbsp;:
</p>
<pre>#!/bin/sh<br /><br />set -e<br /><br /># see http://stackoverflow.com/questions/7665/how-to-resolve-symbolic-links-in-a-shell-script<br /># get the absolute path of the executable<br />SELF_PATH=$(cd -P -- "$(dirname -- "$0")" &amp;&amp; \<br />    pwd -P) &amp;&amp; SELF_PATH=$SELF_PATH/$(basename -- "$0")<br /><br /># resolve symlinks<br />while [ -h $SELF_PATH ]; do<br />    DIR=$(dirname -- "$SELF_PATH")<br />    SYM=$(readlink $SELF_PATH)<br />    SELF_PATH=$(cd $DIR &amp;&amp; cd $(dirname -- "$SYM") &amp;&amp; pwd)/$(basename -- "$SYM")<br />done<br /><br />CUR_DIR=$(dirname "$SELF_PATH")<br /><br />if [ -x "$CUR_DIR/foxstub" ]; then<br />    "$CUR_DIR/foxstub" -app "$CUR_DIR/application.ini" $@<br />else<br />    echo "Error: unable to find Firefox or XULRunner!"<br />fi</pre>
<p>
Nous allons générer notre "application bundle" à la'ide d'un script bash.
Il est vraiment simple, nous avons juste à copier le contenu de notre appli
dans le dossier MacOS. Voici le contenu de <code>build_mac.sh</code>&nbsp;:
</p>
<pre>#!/bin/bash<br /><br /># exit the script on errors<br />set -e<br /><br />TMP_DIR=./tmp<br /><br /># get the absolute path of our TMP_DIR folder<br />TMP_DIR=$(readlink -f -- "$TMP_DIR")<br /><br /># re-create the TMP_DIR folder<br />rm -rfv "$TMP_DIR"<br />mkdir -v "$TMP_DIR"<br /><br /># create the .app folder<br />mkdir -v "$TMP_DIR/MyApp.app"<br /><br /># copy our bundle skeleton<br /># (our launcher myapp-mac.sh and our symbolic link foxstub are included)<br />cp -rv data/bundle_skelet/. "$TMP_DIR/MyApp.app/"<br /><br /># copy our app<br />cp -rv myapp/* "$TMP_DIR/MyApp.app/Contents/MacOS/"<br /><br /># apply the correct permissions<br />chmod -R 755 "$TMP_DIR/MyApp.app"<br /><br /># and copy the result in our main src folder<br />rm -frv MyApp.app<br />cp -Rv  "$TMP_DIR/MyApp.app" ./</pre>
<p>
Ce script sera continuer par la suite. Mais pour le moment, en résultat,
nous avons créer "l'Application Bundle" <code>MyApp.app</code>
dans notre dossier source principal.
</p>
</div>
<div class="howto-section">
<h4><span>4.5 Empaqueter un tar.gz et un dmg</span></h4>
<p>
Pour distribuer notre bundle, nous devons <strong>créer une archive</strong>.
Je propose 2 solutions, chacune avec ses avantages et inconvénients.
</p>
<h5>Créer un tar.gz</h5>
<p>
La première et <strong>la plus simple</strong>, est de <strong>créer un tar.gz</strong>.
Ce format est bien pris en charge par Mac OSX. Le seul problème est l'utilisateur
final risque de ne pas trouver celà très convivial. Voici ce qu'il a à faire&nbsp;:
</p>
<ol>
<li>télécharger le fichier myapp.tar.gz.</li>
<li>l'ouvrir. En fait le comportement par défaut est de décompresser l'archive dans le même dossier.</li>
<li>aller dans le dossier décompressé</li>
<li>déplacer par glisser/déposer le bundle où il le souhaite, par exemple dans /Applications/</li>
</ol>
<p>
Le problème est la phase 2, certains utilisateurs ne comprennent pas que
l'archive est décompressée, et où.
</p>
<p>
pour créer ce tar.gz, nous ajoutons les lignes suivantes dans notre
script <code>build_mac.sh</code>&nbsp;:
</p>
<pre># create a sub-directory for the tar.gz creation<br />mkdir "$TMP_DIR/myapp-1.0"<br /><br /># copy our bundle<br /># (It would be possible to add other files, the license for example)<br />cp -rv "$TMP_DIR/MyApp.app" "$TMP_DIR/myapp-1.0/"<br /><br />rm -fv myapp-mac-1.0.tar.gz<br /><br />cd "$TMP_DIR"<br />tar -zcvf "../myapp-mac-1.0.tar.gz" myapp-1.0<br />cd -</pre>
<h5>Créer un dmg</h5>
<p>
la seconde solution est de <strong>créer une
<a rel="external" href="http://en.wikipedia.org/wiki/Apple_Disk_Image">archive dmg</a></strong>.
En fait c'est un format d'image disque.
<br />
C'est une solution habituelle sur cette plateforme, et utilisée par Firefox par exemple.
</p>
<p>
Nous pouvons <strong>créer un dmg depuis Linux</strong>, mais avec une limitation&nbsp;:
nous ne pouvons pas générer de dmg <strong>compressé</strong>. Enfin en fait il y a une
méthode expérimentale de le faire, que je vais vous proposé ensuite, mais elle est encore
expérimentale.
<br />
<em>L'article le plus utile que j'ai trouvé sur ce sujet est
<a rel="external" href="http://blog.dmdirc.com/2008/06/13/os-x-support-part-2/">ce billet</a>
de l'auteur de DMDirc. Nous allons suivre les mêmes méthodes.</em>
</p>
<p>
La méthode la plus simple sur linux est d'utiliser <code>mkisofs</code>,
ou <code>genisoimage</code>.
<code>genisoimage</code> est un fork du premier, utilisé par certaines distributions,
et comme un lien symbolique nommé <code>mkisofs</code> est également installé par ces
distributions, j'utiliserai la commande <code>mkisofs</code> dans la suite du script.
<br />
Pour l'installer sur Debian/Ubuntu&nbsp;:
</p>
<p><code class="code-xterm-root">apt-get install genisoimage</code></p>
<p>
Nous ajoutons dans notre script <code>build_mac.sh</code>&nbsp;:
</p>
<pre># create the dmg<br />rm -fv myapp-1.0.dmg<br />mkisofs -V 'MyApp' -no-pad -r -apple -o "myapp-1.0.dmg" "$TMP_DIR/myapp-1.0"</pre>
<p>
Avec cette ligne, nous créons le fichier <code>myapp-1.0.dmg</code>, qui contient
tous les fichiers et dossiers inclus dans le dossier <code>$TMP_DIR/myapp-1.0</code>,
avec un nom de volume <code>'MyApp'</code> (le titre de la fenêtre quand le dmg
est monté sur Mac). Et tous les fichiers et dossiers dans le dmg ont les droits 755.
the 755 rights.
</p>
<h5>Compresser ce dmg</h5>
<p>
La seule solution trouvée pour réaliser cette tâche sur Linux, mentionné
dans ce
<a rel="external" href="http://blog.dmdirc.com/2008/06/13/os-x-support-part-2/">billet</a>,
est d'utiliser le programme <code>dmg</code> du projet
<a rel="external" href="http://github.com/planetbeing/libdmg-hfsplus">libdmg-hfsplus</a>.
<br />
L'auteur dit clairement&nbsp;:
</p>
<blockquote>
<p>THE CODE HEREIN SHOULD BE CONSIDERED HIGHLY EXPERIMENTAL</p>
</blockquote>
<p><em>traduction approximative&nbsp;:</em></p>
<blockquote>
<p>CE CODE DOIT ÊTRE CONSIDÉRER COMME HAUTEMENT EXPÉRIMENTAL</p>
</blockquote>
<p>
Noter que le dernier commit du projet que j'ai essayé ne compilait pas
(quelqu'un a rapporté
<a rel="external" href="http://github.com/planetbeing/libdmg-hfsplus/issues#issue/2">le bug</a>).
<br />
Et l'auteur de DMDirc rapporte un autre bug d'une version précédente.
Mais essayer sa
And the author of DMDirc report another bug in a previous version. But I have
tried its <a rel="external" href="http://shanemcc.co.uk/libdmg/">version légèrement modifiée</a>, avec succès&nbsp;!
<br />
Donc vous devriez l'essayer.
</p>
<p>
Voici les lignes ajoutées à notre script&nbsp;:
</p>
<pre># try to compress our dmg, if the the command &lt;dmg&gt; is available<br /># see http://github.com/planetbeing/libdmg-hfsplus<br /># and http://shanemcc.co.uk/libdmg/<br />if [ -x "./tools/dmg" ]; then<br />    # rename temporarily our dmg<br />    mv myapp-1.0.dmg myapp-1.0.dmg.pre<br />    # compress<br />    "./tools/dmg" dmg myapp-1.0.dmg.pre myapp-1.0.dmg<br />    rm -fv myapp-1.0.dmg.pre<br />fi</pre>
<p><em>
Noter que je n'inclus pas le programme <code>dmg</code> dans l'archive jointe,
vous devrez le télécharger vous même depuis les liens précédents, et le
placer dans le dossier <code>tools</code>.
</em></p>
<h5>Créer un dmg depuis Mac OSX</h5>
<p>
pour information, pour créer un dmg directement depuis Mac OSX, il existe le
programme
<a rel="external" href="http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/hdiutil.1.html">hdiutil</a>.
Pour créer un dmg compressé et s'ouvrant automatiquement, d'après un
dossier nommé "myFolder", quelque chose du genre devrait marcher&nbsp;:
</p>
<pre>#!/bin/bash<br /><br />hdiutil create -volname "myapp-1.0" -fs HFS+ -srcfolder "myFolder" -format UDRW myapp-temp.dmg <br /><br />hdiutil convert myapp-temp.dmg -format UDZO -imagekey zlib-level=9 -o myapp.dmg<br /><br />rm -fv myapp-temp.dmg</pre>
<h5>Personnaliser le dmg</h5>
<p>
il est possible de personnaliser notre dmg quand il est  monté, c'est à dire
la fenêtre affichée, par exemple&nbsp;: dimensions de l'icône, image d'arrière plan,
dimensions de la fenêtre...
</p>
<p>
L'idée est de créer un dmg en lecture/écriture sur un mac, de le personnaliser
manuellement, puis de faire une copie du fichier
<a rel="external" href="http://en.wikipedia.org/wiki/.DS_Store">.DS_STORE</a>
et de toutes les autres données. Ensuite nous utiliserons ces données lors
de la création de notre dmg à l'aide de notre script.
<br />
Cette partie ne peut être faite que manuellement et directement depuis un Mac.
</p>
<h6>Créer une image disque en lecture/écriture</h6>
<p>
Sur un Mac, ouvrez "Utilitaires de disque" dans le dossier "Utilitaires".
<br />
Cliquer sur "Nouvelle image".
<br />
Choisissez le <strong>même nom</strong> que le futur nom de volume de notre dmg
(<code>MyApp</code>).
<br />
N'utilisez pas un format journalisé, pour être capable de choisir une
"petite" taille pour ce dmg. La taille importe peu, elle doit juste être
suffisante pour copier notre appli et les autres données.
<br />
Comme <code>format</code> d'image, choisissez <code>image disque en lecture et écriture</code>
Puis cliquer sur "créer".
</p>
<h6>Ajouter nos données sur l'image disque</h6>
<p>
Maintenant montez ce dmg en cliquant dessus. Et ouvrez le.
<br />
Copiez notre appli dans la fenêtre ouverte.
Nous pouvons copier le lien symbolique vers <code>/Applications</code> également,
si il existe. Sinon nous le créerons dans un terminal plus tard.
</p>
<p>
Ouvrez un terminal, depuis les Utilitaires.
<br />
Allez dans l'image disque monté&nbsp;:
<br />
<kbd class="code-xterm">cd /Volumes/MyApp</kbd>
<br />
puis créez un dossier nommé <code>.background</code>&nbsp;:
<br />
<kbd class="code-xterm">mkdir .background</kbd>
<br />
comme ce nom commence par un point (<code>.</code>), ce dossier est caché,
comme sur Linux.
<br />
copiez notre image d'arrière plan dans ce dossier&nbsp;:
<br />
<kbd class="code-xterm">cp pathToOurImage/background.png /Volumes/MyApp/.background/</kbd>
<br />
Et, si besoin, créez le lien symbolique vers /Applications&nbsp;:
<br />
<kbd class="code-xterm">ln -s /Applications /Volumes/MyApp/Applications</kbd>
</p>
<h6>Personnaliser l'image disque</h6>
<p>
Maintenant donnez le focus à la fenêtre du disque monté, et ouvrez
"Afficher les options de présentation" depuis le menu "Présentation"
<br />
Sélectionner <code>Image</code> pour l'airrière plan, puis cliquer sur le bouton.
<br />
Nous devons sélectionner le fichier background.png dans le disque monté,
mais comme ce fichier est dans un dossier caché, nous ne pouvons pas le voir.
Pas d'inquiétude, taper <code>Apple+Shift+G</code>&nbsp;:
<br />
puis taper <code>/Volumes/MyApp/.background/</code>, puis entrée.
<br />
sélectionnez maintenant notre png.
<br />
Choissisez la taille d'icône, par exemple 128, arrangez les par <code>aucun</code>,
puis déplacez les où vous le souhaitez, et adapter la taille de fenêtre
à votre arrière-plan.
</p>
<p>
Maintenant fermer cette fenêtre, et éjecter le disque. Puis monter le de
nouveau, et ouvrez le.
</p>
<h6>Copier la personnalisation créée</h6>
<p>
Dans un terminal, copiez le fichier <code>.DS_STORE</code> créé à la racine
du disque monté&nbsp;:
<br />
<kbd class="code-xterm">cp /Volumes/MyApp/.DS_STORE pathToSave/myDS_STORE</kbd>
</p>
<p>
Maintenant nous avons enfin tous les fichiers nécessaires pour notre script,
nous avons juste à copier le fichier .DS_STORE  et le dossier .background avec
le fichier background.png . Le dmg que nous créerons aura la même personnalisation.
<br />
Copions ces données dans nos sources&nbsp;:
</p>
<pre>    |- samples_chapter_4/<br />        |- data/<br />            |- bundle_skelet/<br />            |- dmg_extra_data/<br />                |- .background/<br />                    |- background.png<br />                |- Applications<br />                |- .DS_STORE</pre>
<p>
Et nous ajoutons les lignes suivantes à notre script <code>build_mac.sh</code>,
avant de créer le dmg&nbsp;:
</p>
<pre># copy eventual extra data, by example a symbolic link to /Applications<br />if [ $(ls -A "data/dmg_extra_data" | wc -c) -ne 0 ]; then<br />    cp -Rv data/dmg_extra_data/. "$TMP_DIR/myapp-1.0/"<br />fi</pre>
<p>
<em>
Notez que cette <strong>personnalisation est dépendente du nom de volume utilisé</strong>,
en particulier pour l'image d'arrière plan, parce que le fichier <code>.DS_STORE</code>
utilise des chemins absolus vers le disque monté, et le nom de volume en fait partie.
<br />
Donc si vous changer le nom de volume, vous devez recréer manuellement cette
personnalisation...
</em>
</p>
<h5>Lancer notre script de build</h5>
<p>Pour lancer notre script (sur Linux), et créer nos dmg et tar.gz, dans un terminal&nbsp;:</p>
<ul class="code-xterm">
<li><pre>cd samples_chapter_4</pre></li>
<li><pre>sh ./build_mac.sh</pre></li>
</ul>
<p>
Et, en résultat, nous avons finalement le dossier <code>MyApp.app</code>,
et les fichiers <code>myapp-1.0.dmg</code> et <code>myapp-1.0.tar.gz</code>
dans notre dossier de source principal.
</p>
</div>
<div class="howto-navigator-bottom">
<div class="howto-previous"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribuer-votre-appli-XULRunner-3-Windows" title="Aller au chapitre 3">&lt; chapitre précédent</a></div>
<div class="howto-next"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/Distribuer-votre-appli-XULRunner-5-Synthese-toutes-plateformes" title="Aller au chapitre 5">chapitre suivant &gt;</a></div>
<div class="clearer">&nbsp;</div>
</div>
<div class="howto-author">
<p>Nicolas Martin</p>
</div>
<div class="howto-download-section">
<p>
Vous pouvez télécharger tous les exemples de ce chapitre 4 (Mac OSX) dans l'archive
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/dl.php?id=current_sample_4" class="howto-download-archive">
samples_chapter_4.tar.gz
</a>.
</p>
</div>
<div class="howto-credits">
<p><em>
L'application myapp, de
<a href="https://developer.mozilla.org/en/getting_started_with_xulrunner" rel="external">developer.mozilla.org</a>,
est dans le <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domaine Public</a>.
</em></p>
<p><em>
L'icône utilisée est issue du
<a href="http://tango.freedesktop.org" rel="external">Tango Desktop Project</a>,
et est dans le <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domaine Public</a>.
</em></p>
<p><em>
Toutes les autres données ajoutées, et les fichiers en exemple, de ce chapitre 4, sont dans le
<a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domain Public</a> également.
</em></p>
</div>
<div class="howto-footer">
<p>
Le contenu de cet article est sous les termes de la licence
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>
</p>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width: 0;" src="http://i.creativecommons.org/l/by-sa/3.0/80x15.png" /></a>
</div>
</div>]]></content:encoded>
</item>
     <item rdf:about="http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribute-your-XULRunner-app-4-Mac-OSX">
    <title>Distribute your XULRunner app - 4 - Mac OSX</title>
    <link>http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribute-your-XULRunner-app-4-Mac-OSX</link>
    <dc:date>2011-05-26T14:54:00+00:00</dc:date>
    <dc:language>fr</dc:language>
    <dc:creator>Joliclic blog - mozilla</dc:creator>
    <dc:subject></dc:subject>
	<description></description>
	<content:encoded><![CDATA[    <div class="howto">
<p><em>Ce billet existe aussi en <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribuer-votre-appli-XULRunner-4-Mac-OSX">français</a></em></p>
<p><em>
This post is part of a <a href="http://joliclic.free.fr/blog/index.php?tag/dist_xul_app_en">series</a> about how to package a XULRunner application.<br />
See the <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/20/Distribute-your-XULRunner-app-1-Preamble">preamble</a> for the context case.
</em></p>
<h3><span>4 - Mac OSX</span></h3>
<ul>
<li>4.1 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/#howto_dxr_4.1">Icons for Mac OSX</a></li>
<li>4.2 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/#howto_dxr_4.2">Create a launcher</a></li>
<li>4.3 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/#howto_dxr_4.3">Some Mac specificities</a></li>
<li>4.4 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/#howto_dxr_4.4">Create a Application Bundle</a></li>
<li>4.5 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/#howto_dxr_4.5">Package as tar.gz and dmg</a></li>
</ul>
<div class="howto-section">
<h4><span>4.1 Icons for Mac OSX</span></h4>
<p>
We need a <strong><a href="http://en.wikipedia.org/wiki/Icns" rel="external">icns</a></strong>
icon. On Mac the windows doesn't have a icon, but, later,
we will use one in the Dock. And it will be used for the bundle that we will
create.
</p>
<p>
We can generate this <code>.icns</code> file directly from Linux. The
restriction is that we cannot embed mutiple color depth images, but
multiple sizes is possible.
<br />
We need the program <code>png2icns</code> from the <strong>icnsutils</strong> package.
<br />
On Debian/Ubuntu:
</p>
<p><code class="code-xterm-root">apt_get install icnsutils</code></p>
<p>We obtain our icns file from several png with:</p>
<p><kbd class="code-xterm">png2icns icon.icns icon128.png icon48.png icon32.png icon16.png</kbd></p>
<p><em>
You can find a bash script with this command line in the sample archive
related to this chapter 4 (in <code>samples_chapter_4/data/icons/</code>).
</em></p>
</div>
<div class="howto-section">
<h4><span>4.2 Create a launcher</span></h4>
<p>
Like for Linux, we will use a <strong>shell script</strong> for our
<strong>launcher</strong>. But we have several problems to resolve.
</p>
<p>
The first one is not too difficult. The <code>readlink</code> program
available on Mac OSX is not the GNU one, and we can't use the
<code>-f</code> option. We will resolve ourself this functionality.
</p>
<p>
A more serious problem, is that <em>we can't determine where Firefox is
installed</em>. So, here, we will impose a limitation,
<em>Firefox <strong>must</strong> be installed in its default location</em>,
i.e. <code>/Applications/</code> .
</p>
<p><em>
Note: if you have any suggestions to determine where is installed Firefox,
please let me know ;) .
</em></p>
<p>
Here this script, <code><strong>myapp-mac.sh</strong></code>, but that's
not exactly this one we will use later:
</p>
<pre>#!/bin/sh<br /><br />set -e<br /><br /># see http://stackoverflow.com/questions/7665/how-to-resolve-symbolic-links-in-a-shell-script<br /># get the absolute path of the executable<br />SELF_PATH=$(cd -P -- "$(dirname -- "$0")" &amp;&amp; \<br />    pwd -P) &amp;&amp; SELF_PATH=$SELF_PATH/$(basename -- "$0")<br /><br /># resolve symlinks<br />while [ -h $SELF_PATH ]; do<br />    DIR=$(dirname -- "$SELF_PATH")<br />    SYM=$(readlink $SELF_PATH)<br />    SELF_PATH=$(cd $DIR &amp;&amp; cd $(dirname -- "$SYM") &amp;&amp; pwd)/$(basename -- "$SYM")<br />done<br /><br />CUR_DIR=$(dirname "$SELF_PATH")<br /><br />if [ -x /Applications/Firefox.app/Contents/MacOS/firefox-bin ]; then<br />    /Applications/Firefox.app/Contents/MacOS/firefox-bin -app "$CUR_DIR/application.ini" $@<br />elif [ -x /Library/Frameworks/XUL.framework/xulrunner-bin ]; then<br />    /Library/Frameworks/XUL.framework/xulrunner-bin "$CUR_DIR/application.ini" $@<br />else<br />    echo "Error: unable to find Firefox or XULRunner!"<br />fi</pre>
<p>
If we try this launcher, we can see  2 other problems, the icon shown in the dock
is the Firefox one, and the main menu, when we close all our app windows, is the Firefox one.
<br />
There is a solution to these problems, as we will see in the next parts.
</p>
<p>
<em>Note that if you really want to use a such script, without a bundle,
you may want use a <code>.command</code> extension rather than <code>.sh</code>,
because then the file can be double-clicked in the Mac Finder, this will
open a terminal then the app.</em>
</p>
</div>
<div class="howto-section">
<h4><span>4.3 Some Mac specificities</span></h4>
<p>
There is a particularity on Mac, there is a <strong>main Menu</strong>
controlled by the operating system, corresponding to the current focused
application. And when all windows of a same application are closed, this
menu still appeared, as long as the application quit.
</p>
<p>
This is well handled by a XULRunner application, but we must add some
code for that.
</p>
<p>Some documentation on MDN:</p>
<ul>
<li>
<a rel="external" href="https://developer.mozilla.org/en/XUL_School/Adding_menus_and_submenus#Menus_on_Mac_OS_X">Menus on Mac OS X</a>
</li>
<li>
<a rel="external" href="https://developer.mozilla.org/en/XULRunner/MacFAQ#UI_notes">MacFAQ: UI_notes</a>
</li>
</ul>
<p>
If your app uses a main <code>menubar</code> element, XULRunner/Firefox
will use it (in fact the first menubar) to create this special menu. If
you don't have one, you should create it, hidden by default for the other
platforms, this will allow the menu construction anyway.
</p>
<p>
The entries in the apple menu are constructed from elements with
reserved <code>id</code>. You should at least create some entries, to
allow to quit the app for example.
</p>
<p>
Here's the list of available id corresponding to these entries
(<a rel="external" href="http://mxr.mozilla.org/mozilla1.9.2/source/widget/src/cocoa/nsMenuBarX.mm#564">sources</a>):
</p>
<table>
<thead>
<tr>
<th>element id</th>
<th>corresponding menu item</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>aboutName</code></td>
<td>About This App</td>
</tr>
<tr>
<td><code>menu_preferences</code></td>
<td>Preferences...</td>
</tr>
<tr>
<td><code>menu_mac_services</code></td>
<td>Services</td>
</tr>
<tr>
<td><code>menu_mac_hide_app</code></td>
<td>Hide App</td>
</tr>
<tr>
<td><code>menu_mac_hide_others</code></td>
<td>Hide Others</td>
</tr>
<tr>
<td><code>menu_mac_show_all</code></td>
<td>Show All</td>
</tr>
<tr>
<td><code>menu_FileQuitItem</code></td>
<td>Quit</td>
</tr>
</tbody>
</table>
<p>
And here's an example of a minimal xul menu for this usage:
</p>
<pre>  &lt;commandset id="main-commands"&gt;<br />      &lt;command id="cmd:quit" oncommand="myappQuitApplication();"/&gt;<br />  &lt;/commandset&gt;<br />  <br />  &lt;keyset id="ui-keys"&gt;<br />      &lt;key id="key:quitApp" key="Q" modifiers="accel" command="cmd:quit"/&gt;<br />      &lt;key id="key:hideApp" key="H" modifiers="accel"/&gt;<br />      &lt;key id="key:hideOthersApp" key="H" modifiers="accel,alt"/&gt;<br />  &lt;/keyset&gt;<br />  <br />  &lt;menubar id="main-menubar" hidden="true"&gt;<br />      &lt;menu id="mac-menu"&gt;<br />          &lt;menupopup&gt;<br />              &lt;menuitem id="menu_mac_hide_app" label="Hide My App" key="key:hideApp"/&gt;<br />              &lt;menuitem id="menu_mac_hide_others" label="Hide Others" key="key:hideOthersApp"/&gt;<br />              &lt;menuitem id="menu_mac_show_all" label="Show All"/&gt;<br />              &lt;menuitem id="menu_FileQuitItem" label="Quit" key="key:quitApp" command="cmd:quit"/&gt;<br />          &lt;/menupopup&gt;<br />      &lt;/menu&gt;<br />  &lt;/menubar&gt;</pre>
<p>
Of course, like the other part of the app, the strings used in the labels and keys
<a rel="external" href="https://developer.mozilla.org/en/Localization"><strong>should be localized</strong></a>.
But that's not the purpose of this howto.
</p>
<p>
The <code>myappQuitApplication</code> function has been added in the
<code>main.js</code> file of the our app:
</p>
<pre>function myappQuitApplication() {<br />  const Cc = Components.classes;<br />  const Ci = Components.interfaces;<br />    <br />  let appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].<br />                   getService(Ci.nsIAppStartup);<br />  appStartup.quit(Ci.nsIAppStartup.eAttemptQuit);<br />  <br />  return true;<br />}</pre>
<p>
Finally, the last problem: when all windows of our app are closed,
in fact the app doesn't quit, and the main menu remains. More, as is,
this is the Firefox menu that we see.
<br />
In fact, there is a special hidden window that XULRunner uses for this menu.
So we have to create a such window, and to set a preference to specify it.
</p>
<p>Here's the added preference in <code>defaults/preferences/pref.js</code>:</p>
<pre>pref("browser.hiddenWindowChromeURL", "chrome://myapp/content/hiddenWindow.xul");</pre>
<p>And the content of <code>hiddenWindow.xul</code>, which contains only our main menubar:</p>
<pre>&lt;window id="hiddenWindow"<br />        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"&gt;<br />    &lt;script type="application/javascript"&gt;<br />    &lt;![CDATA[<br />function myappQuitApplication() {<br />    const Cc = Components.classes;<br />    const Ci = Components.interfaces;<br />    <br />    let appStartup = Cc['@mozilla.org/toolkit/app-startup;1'].<br />                     getService(Ci.nsIAppStartup);<br />    appStartup.quit(Ci.nsIAppStartup.eAttemptQuit);<br />    <br />    return true;<br />}<br />    ]]&gt;<br />    &lt;/script&gt;<br />  <br />    &lt;commandset id="main-commands"&gt;<br />        &lt;command id="cmd:quit" oncommand="myappQuitApplication();"/&gt;<br />    &lt;/commandset&gt;<br />    <br />    &lt;keyset id="ui-keys"&gt;<br />        &lt;key id="key:quitApp" key="Q" modifiers="accel" command="cmd:quit"/&gt;<br />        &lt;key id="key:hideApp" key="H" modifiers="accel"/&gt;<br />        &lt;key id="key:hideOthersApp" key="H" modifiers="accel,alt"/&gt;<br />    &lt;/keyset&gt;<br />    <br />    &lt;menubar id="main-menubar" hidden="true"&gt;<br />        &lt;menu id="mac-menu"&gt;<br />            &lt;menupopup&gt;<br />                &lt;menuitem id="menu_mac_hide_app" label="Hide My App" key="key:hideApp"/&gt;<br />                &lt;menuitem id="menu_mac_hide_others" label="Hide Others" key="key:hideOthersApp"/&gt;<br />                &lt;menuitem id="menu_mac_show_all" label="Show All"/&gt;<br />                &lt;menuitem id="menu_FileQuitItem" label="Quit" key="key:quitApp" command="cmd:quit"/&gt;<br />            &lt;/menupopup&gt;<br />        &lt;/menu&gt;<br />    &lt;/menubar&gt;<br />&lt;/window&gt;</pre>
</div>
<div class="howto-section">
<h4><span>4.4 Create a Application Bundle</span></h4>
<p>
On Mac OSX, applications are packaged in a special format named
<strong>Application Bundle</strong>. This is in fact a folder, named with
<code>.app</code> as extension, and with a special structure.
</p>
<p>Some useful documentation:</p>
<ul>
<li><a rel="external" href="http://www.mactipsandtricks.com/articles/Wiley_HT_appBundles2.lasso">Inside Application Bundles</a></li>
<li><a rel="external" href="http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPRuntimeConfig/000-Introduction/introduction.html">Runtime Configuration Guidelines: Introduction</a></li>
<li><a rel="external" href="https://developer.mozilla.org/en/XULRunner/Creating_custom_app_bundles_for_Mac_OS_X">Custom app bundles for Mac OS X</a></li>
</ul>
<p>Here's a proposal <code>.app</code> folder for our app:</p>
<pre>    |- MyApp.app/<br />        |- Contents/<br />            |- MacOS/<br />                |- chrome/<br />                |- defaults/<br />                |- application.ini<br />                |- chrome.manifest<br />                |- foxstub<br />                |- myapp-mac.sh<br />            |- Resources/<br />                |- myapp.icns<br />            |- Info.plist<br />            |- PkgInfo</pre>
<p>
The <code><strong>MacOS</strong></code> folder contains in fact all the
files and folders of our XULRunner app.
</p>
<p>
The <code><strong>Resources</strong></code> folder contains only our icon
in icns format.
</p>
<p>
The <code><strong>PkgInfo</strong></code> file contains only the string
<code>APPL????</code>. I'm not sure this file is really necessary, it's
seems it's important for compatibilty with Mac OS 9.
<br />
The value specifies that this bundle is an application, and as we don't have
a valid 4 characters identifier, we use 4 question marks (<code>????</code>).
</p>
<p>
The <code><strong>Info.plist</strong></code> file describe our app:
</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;<br />&lt;plist version="1.0"&gt;<br />&lt;dict&gt;<br />	&lt;key&gt;CFBundleDevelopmentRegion&lt;/key&gt;<br />	&lt;string&gt;English&lt;/string&gt;<br />	&lt;key&gt;CFBundleExecutable&lt;/key&gt;<br />	&lt;string&gt;myapp-mac.sh&lt;/string&gt;<br />	&lt;key&gt;CFBundleGetInfoString&lt;/key&gt;<br />	&lt;string&gt;MyApp 1.0&lt;/string&gt;<br />	&lt;key&gt;CFBundleIconFile&lt;/key&gt;<br />	&lt;string&gt;myapp&lt;/string&gt;<br />	&lt;key&gt;CFBundleIdentifier&lt;/key&gt;<br />	&lt;string&gt;net.yourcompany.myapp&lt;/string&gt;<br />	&lt;key&gt;CFBundleInfoDictionaryVersion&lt;/key&gt;<br />	&lt;string&gt;6.0&lt;/string&gt;<br />	&lt;key&gt;CFBundleName&lt;/key&gt;<br />	&lt;string&gt;MyApp&lt;/string&gt;<br />	&lt;key&gt;CFBundlePackageType&lt;/key&gt;<br />	&lt;string&gt;APPL&lt;/string&gt;<br />	&lt;key&gt;CFBundleShortVersionString&lt;/key&gt;<br />	&lt;string&gt;1.0.0.0&lt;/string&gt;<br />	&lt;key&gt;CFBundleSignature&lt;/key&gt;<br />	&lt;string&gt;????&lt;/string&gt;<br />	&lt;key&gt;CFBundleVersion&lt;/key&gt;<br />	&lt;string&gt;1.0.0.0&lt;/string&gt;<br />	&lt;key&gt;NSAppleScriptEnabled&lt;/key&gt;<br />	&lt;true/&gt;<br />&lt;/dict&gt;<br />&lt;/plist&gt;</pre>
<p>Some comment on these properties:</p>
<p>
The <code><strong>CFBundleExecutable</strong></code> point to our launcher,
the shell script named <code>myapp-mac.sh</code>.
</p>
<p>
The value of <code><strong>CFBundleIconFile</strong></code> is
<code>myapp</code> because our icon in the Resources folder is named
<code><strong>myapp</strong>.icns</code>. Now, the end user sees our bundle
with our icon.
</p>
<p>
The <code><strong>CFBundleIdentifier</strong></code> is formatted as
an <code>inversed domain name dot application name</code>. It must be a unique
identifier for our app.
</p>
<p>
The <code><strong>CFBundlePackageType</strong></code> specifies that this is an
application bundle (<code>APPL</code>).
</p>
<p>
The value of <code><strong>CFBundleSignature</strong></code> is
<code>????</code> because we don't have a signature. This is supposed to
be an unique 4 characters identifier, and supposed to be obtained by an
Apple registration. As I understand this is required essentially for
Mac OS 9. Don't worry, I have not seen any problem with our value ;) .
</p>
<p>
Now let's see <strong>a nice trick</strong>. As is, the end user sees our
app with our icon, but when he launches it, the icon in the Dock is the
Firefox one.
<br />
In the tree folder of our bundle, you can see a file named
<code><strong>foxstub</strong></code>, this file is in fact
<strong>a symbolic link to the Firefox executable</strong>.
</p>
<p>This link is obtained simply, in the MacOS folder, with:</p>
<p>
<kbd class="code-xterm">ln -s /Applications/Firefox.app/Contents/MacOS/firefox-bin foxstub</kbd>
</p>
<p>
Now when the user launches our app, this is our icon that's displayed in
the dock :) .
</p>
<p><em>
In fact, our icon appears in the dock, then disappears, and appears again,
because our script is launched, then the linked executable. But that's
not a big problem.
</em></p>
<p>
Here's the modified launcher script <code>myapp-mac.sh</code>, which now
uses the symbolic link to firefox:
</p>
<pre>#!/bin/sh<br /><br />set -e<br /><br /># see http://stackoverflow.com/questions/7665/how-to-resolve-symbolic-links-in-a-shell-script<br /># get the absolute path of the executable<br />SELF_PATH=$(cd -P -- "$(dirname -- "$0")" &amp;&amp; \<br />    pwd -P) &amp;&amp; SELF_PATH=$SELF_PATH/$(basename -- "$0")<br /><br /># resolve symlinks<br />while [ -h $SELF_PATH ]; do<br />    DIR=$(dirname -- "$SELF_PATH")<br />    SYM=$(readlink $SELF_PATH)<br />    SELF_PATH=$(cd $DIR &amp;&amp; cd $(dirname -- "$SYM") &amp;&amp; pwd)/$(basename -- "$SYM")<br />done<br /><br />CUR_DIR=$(dirname "$SELF_PATH")<br /><br />if [ -x "$CUR_DIR/foxstub" ]; then<br />    "$CUR_DIR/foxstub" -app "$CUR_DIR/application.ini" $@<br />else<br />    echo "Error: unable to find Firefox or XULRunner!"<br />fi</pre>
<p>
We will generate our application bundle with a bash script.
It's very simple, we have just to copy the content of our app into the MacOS
folder. Here's the content of <code>build_mac.sh</code>:
</p>
<pre>#!/bin/bash<br /><br /># exit the script on errors<br />set -e<br /><br />TMP_DIR=./tmp<br /><br /># get the absolute path of our TMP_DIR folder<br />TMP_DIR=$(readlink -f -- "$TMP_DIR")<br /><br /># re-create the TMP_DIR folder<br />rm -rfv "$TMP_DIR"<br />mkdir -v "$TMP_DIR"<br /><br /># create the .app folder<br />mkdir -v "$TMP_DIR/MyApp.app"<br /><br /># copy our bundle skeleton<br /># (our launcher myapp-mac.sh and our symbolic link foxstub are included)<br />cp -rv data/bundle_skelet/. "$TMP_DIR/MyApp.app/"<br /><br /># copy our app<br />cp -rv myapp/* "$TMP_DIR/MyApp.app/Contents/MacOS/"<br /><br /># apply the correct permissions<br />chmod -R 755 "$TMP_DIR/MyApp.app"<br /><br /># and copy the result in our main src folder<br />rm -frv MyApp.app<br />cp -Rv  "$TMP_DIR/MyApp.app" ./</pre>
<p>
This script will be continued in the next parts. But for the moment,
as result, we have created the Application Bundle <code>MyApp.app</code>
into our main source folder.
</p>
</div>
<div class="howto-section">
<h4><span>4.5 Package as tar.gz and dmg</span></h4>
<p>
To distribute our bundle, we need to <strong>create an archive</strong>.
I propose here 2 solutions, each with advantages and disadvantages.
</p>
<h5>Create a tar.gz</h5>
<p>
The first and the <strong>simplest</strong>, is to <strong>create a tar.gz</strong>.
This format is well handled by Mac OSX. The only problem, is that the
final user can find it not really friendly. Here what's he have to do:
</p>
<ol>
<li>download the myapp.tar.gz file.</li>
<li>open it. In fact the default behavior is to uncompress the archive into the same folder.</li>
<li>go into the uncompressed folder</li>
<li>move by drag and drop the bundle where he wants, for example in /Applications/</li>
</ol>
<p>
The problem is phase 2, some users doesn't understand that the archive
is uncompressed, and where.
</p>
<p>To create this tar.gz, we add the following lines in our <code>build_mac.sh</code> script:</p>
<pre># create a sub-directory for the tar.gz creation<br />mkdir "$TMP_DIR/myapp-1.0"<br /><br /># copy our bundle<br /># (It would be possible to add other files, the license for example)<br />cp -rv "$TMP_DIR/MyApp.app" "$TMP_DIR/myapp-1.0/"<br /><br />rm -fv myapp-mac-1.0.tar.gz<br /><br />cd "$TMP_DIR"<br />tar -zcvf "../myapp-mac-1.0.tar.gz" myapp-1.0<br />cd -</pre>
<h5>Create a dmg</h5>
<p>
The second solution is to <strong>create a
<a rel="external" href="http://en.wikipedia.org/wiki/Apple_Disk_Image">dmg archive</a></strong>.
In fact this is a disk image format.
<br />
This is a usual solution on this platform, and used by Firefox for example.
</p>
<p>
We can <strong>create a dmg from Linux</strong>, but with a limitation:
we can't generate a <strong>compressed</strong> dmg.
Well, in fact there's a experimental way to do it, that I will propose to
you just after, but it's still experimental.
<br />
<em>The most useful article that I have found about this subject is
<a rel="external" href="http://blog.dmdirc.com/2008/06/13/os-x-support-part-2/">this post</a>
from the author of DMDirc. We will follow the same methods.</em>
</p>
<p>
The easiest way on linux is to use <code>mkisofs</code>, or <code>genisoimage</code>.
<code>genisoimage</code> is a fork of the former, used in some distributions, and as
a symlink named <code>mkisofs</code> is installed as well on these distributions, I will
use the command <code>mkisofs</code> in the following script.
<br />
To install it on Debian/Ubuntu:
</p>
<p><code class="code-xterm-root">apt-get install genisoimage</code></p>
<p>
We add, in our build script <code>build_mac.sh</code>:
</p>
<pre># create the dmg<br />rm -fv myapp-1.0.dmg<br />mkisofs -V 'MyApp' -no-pad -r -apple -o "myapp-1.0.dmg" "$TMP_DIR/myapp-1.0"</pre>
<p>
With this line, we create the file <code>myapp-1.0.dmg</code>, which contains
all files and folders included in the <code>$TMP_DIR/myapp-1.0</code> folder,
with the volume name  <code>'MyApp'</code> (the title of the window when the dmg
is mounted on Mac). And all files and folders in the dmg have
the 755 rights.
</p>
<h5>Compress this dmg</h5>
<p>
The only solution found to perform this task on Linux, mentioned in this
<a rel="external" href="http://blog.dmdirc.com/2008/06/13/os-x-support-part-2/">post</a>,
is to use the <code>dmg</code> program from the
<a rel="external" href="http://github.com/planetbeing/libdmg-hfsplus">libdmg-hfsplus</a>
project.
<br />
The author clearly says:
</p>
<blockquote>
<p>THE CODE HEREIN SHOULD BE CONSIDERED HIGHLY EXPERIMENTAL</p>
</blockquote>
<p>
Note that the last commit of the project that I have tried doesn't compile
(somebody have reported
<a rel="external" href="http://github.com/planetbeing/libdmg-hfsplus/issues#issue/2">the bug</a>).
<br />
And the author of DMDirc report another bug in a previous version. But I have
tried its <a rel="external" href="http://shanemcc.co.uk/libdmg/">slightly modified version</a>, with success!
<br />
So, you should give it a try.
</p>
<p>
Here the added lines to our build script:
</p>
<pre># try to compress our dmg, if the the command &lt;dmg&gt; is available<br /># see http://github.com/planetbeing/libdmg-hfsplus<br /># and http://shanemcc.co.uk/libdmg/<br />if [ -x "./tools/dmg" ]; then<br />    # rename temporarily our dmg<br />    mv myapp-1.0.dmg myapp-1.0.dmg.pre<br />    # compress<br />    "./tools/dmg" dmg myapp-1.0.dmg.pre myapp-1.0.dmg<br />    rm -fv myapp-1.0.dmg.pre<br />fi</pre>
<p><em>
Note that I don't include the <code>dmg</code> program in the joined
archive, you have to download it yourself from the previous links, and
place it into the <code>tools</code> folder.
</em></p>
<h5>Create a dmg from Mac OSX</h5>
<p>
For information, to create a dmg directly on Mac OSX, there's the program
<a rel="external" href="http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/hdiutil.1.html">hdiutil</a>.
To create an auto open, compressed, dmg, from a folder named "myFolder",
something like this should work:
</p>
<pre>#!/bin/bash<br /><br />hdiutil create -volname "myapp-1.0" -fs HFS+ -srcfolder "myFolder" -format UDRW myapp-temp.dmg <br /><br />hdiutil convert myapp-temp.dmg -format UDZO -imagekey zlib-level=9 -o myapp.dmg<br /><br />rm -fv myapp-temp.dmg</pre>
<h5>Customize the dmg</h5>
<p>
It's possible to customize our dmg when it is mounted, i.e. the displayed
window, for example: icon size, background image, window size...
</p>
<p>
The idea is to create a read/write dmg on a mac, customize it manually, and then
make a copy of the file <a rel="external" href="http://en.wikipedia.org/wiki/.DS_Store">.DS_STORE</a>
and all the data. Later we will use these data
when we will create our dmg by script.
<br />
This part can only be done directly and manually on a Mac.
</p>
<h6>create a read/write disk image</h6>
<p>
On a Mac, open "Disk Utility" from the "Utilities" folder.
<br />
Click on "New Image".
<br />
Choose the <strong>same name</strong> as the future volume name of our dmg
(<code>MyApp</code>).
<br />
Don't use a journaled format, to be able to select a "small" size for
this dmg. The size doesn't matter, it have to be big enough to copy our
app and other data.
<br />
As <code>Image Format</code>, choose <code>read/write disk image</code>.
Then click on "create".
</p>
<h6>Add our data on the disk image</h6>
<p>
Now mount this dmg by clicking on it. And open it.
<br />
Copy our app in the open window.
We can copy the symbolic link to <code>/Applications</code> too, if it
exists. Otherwise we will create it in a terminal later.
</p>
<p>
Open a Terminal from the Utilities.
<br />
Go into the mounted disk image:
<br />
<kbd class="code-xterm">cd /Volumes/MyApp</kbd>
<br />
then create a folder named <code>.background</code>:
<br />
<kbd class="code-xterm">mkdir .background</kbd>
<br />
because the name begin by a dot (<code>.</code>), this folder is hidden, like on Linux.
<br />
copy in this  folder our background image:
<br />
<kbd class="code-xterm">cp pathToOurImage/background.png /Volumes/MyApp/.background/</kbd>
<br />
And, if needed, create the symbolic link to /Applications:
<br />
<kbd class="code-xterm">ln -s /Applications /Volumes/MyApp/Applications</kbd>
</p>
<h6>Customize the disk image</h6>
<p>
Now give the focus to the window of the mounted disk, and open "Show View Options"
from the View menu.
<br />
Select <code>picture</code> for background, then click on the button.
<br />
We have to select the background.png file from the mounted disk, but because
this png is in a hidden folder we can't see it. Don't worry, type
<code>Apple+Shift+G</code>:
<br />
then type <code>/Volumes/MyApp/.background/</code>, then enter.
<br />
now select our png.
<br />
Choose the icon size, for example 128, arrange them by <code>none</code>,
then drag them where you want, and adapt the window size to our background.
</p>
<p>
Now close this window, and eject the mounted disk. Then mount it again, and open it.
</p>
<h6>Copy the resulting customization</h6>
<p>
In a terminal, copy the created file <code>.DS_STORE</code> at the root
of the mounted disk:
<br />
<kbd class="code-xterm">cp /Volumes/MyApp/.DS_STORE pathToSave/myDS_STORE</kbd>
</p>
<p>
Now we have finally all needed files. When we create our dmg from our
script, we just have to copy the file .DS_STORE and the folder
.background with the file background.png. The resulting dmg will have
the same customization.
<br />
Copy these data into our sources:
</p>
<pre>    |- samples_chapter_4/<br />        |- data/<br />            |- bundle_skelet/<br />            |- dmg_extra_data/<br />                |- .background/<br />                    |- background.png<br />                |- Applications<br />                |- .DS_STORE</pre>
<p>
And we add the following lines in our <code>build_mac.sh</code> script,
before creating the dmg:
</p>
<pre># copy eventual extra data, by example a symbolic link to /Applications<br />if [ $(ls -A "data/dmg_extra_data" | wc -c) -ne 0 ]; then<br />    cp -Rv data/dmg_extra_data/. "$TMP_DIR/myapp-1.0/"<br />fi</pre>
<p>
<em>
Note that this <strong>customization is dependent of the used volume name</strong>,
especially the background image, because the <code>.DS_STORE</code>
file uses absolute paths to the mounted disk, and the volume name is
part of it.
<br />
So, if you change the volume name, you have to recreate manually the customization...
</em>
</p>
<h5>Launch our build script</h5>
<p>To launch our script (on Linux), and create our dmg and tar.gz, in a terminal:</p>
<ul class="code-xterm">
<li><pre>cd samples_chapter_4</pre></li>
<li><pre>sh ./build_mac.sh</pre></li>
</ul>
<p>
And as result, we have finally the folder <code>MyApp.app</code>,
and the files <code>myapp-1.0.dmg</code> and <code>myapp-1.0.tar.gz</code>
in our main source folder.
</p>
</div>
<div class="howto-navigator-bottom">
<div class="howto-previous"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribute-your-XULRunner-app-3-Windows" title="Go to chapter 3">&lt; previous chapter</a></div>
<div class="howto-next"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/27/Distribute-your-XULRunner-app-5-Synthesis-all-platforms" title="Go to chapter 5">next chapter &gt;</a></div><div class="clearer">&nbsp;</div>
</div>
<div class="howto-author">
<p>Nicolas Martin</p>
</div>
<div class="howto-download-section">
<p>
You can download all the samples of this chapter 4 (Mac OSX) in the
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/dl.php?id=current_sample_4" class="howto-download-archive">samples_chapter_4.tar.gz</a>
archive.
</p>
</div>
<div class="howto-credits">
<p><em>
The myapp application, from
<a href="https://developer.mozilla.org/en/getting_started_with_xulrunner" rel="external">developer.mozilla.org</a>
is in the <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a>.
</em></p>
<p><em>
The icon used is from the
<a href="http://tango.freedesktop.org" rel="external">Tango Desktop Project</a>,
and is in the <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a>.
</em></p>
<p><em>
All other added data, and sample files, of this chapter 4, are in the
<a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a> too.
</em></p>
</div>
<div class="howto-footer">
<p>
The content of this article
is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>
</p>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width: 0;" src="http://i.creativecommons.org/l/by-sa/3.0/80x15.png" /></a>
</div>
</div>]]></content:encoded>
</item>
     <item rdf:about="http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribuer-votre-appli-XULRunner-3-Windows">
    <title>Distribuer votre appli XULRunner - 3 - Windows</title>
    <link>http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribuer-votre-appli-XULRunner-3-Windows</link>
    <dc:date>2011-05-25T12:27:00+00:00</dc:date>
    <dc:language>fr</dc:language>
    <dc:creator>Joliclic blog - mozilla</dc:creator>
    <dc:subject></dc:subject>
	<description></description>
	<content:encoded><![CDATA[    <div class="howto">
<p><em>This post exists also in <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribute-your-XULRunner-app-3-Windows">english</a></em></p>
<p><em>
Ce billet fait partie d'une <a href="http://joliclic.free.fr/blog/index.php?tag/dist_xul_app_fr">série</a> sur comment déployer une application XULRunner.
Voir le <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/20/Distribuer-votre-appli-XULRunner-1-Preambule">préambule</a> pour le contexte.
</em></p>
<h3><span>3 - Windows</span></h3>
<ul>
<li>3.1 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/#howtofr_dxr_3.1">Icônes pour Windows</a></li>
<li>3.2 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/#howtofr_dxr_3.2">Créer un lanceur (batch ou C)</a></li>
<li>3.3 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/#howtofr_dxr_3.3">Créer un script NSIS</a></li>
<li>3.4 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/#howtofr_dxr_3.4">Créer l'installeur</a></li>
</ul>
<div class="howto-section">
<h4><span>3.1 Icônes pour Windows</span></h4>
<p>
Nous avons besoin d'une icône au format .ico. Elle sera utilisée par nos
fenêtres, et par notre lanceur.
</p>
<p>
Il est facile de faire un fichier .ico sur Linux, nous avons juste besoin
du programme <code>icotool</code>, disponible dans le paquet <code>icoutils</code>.
<br />
Sur Debian/Ubuntu&nbsp;:
</p>
<p><code class="code-xterm-root">apt-get install icoutils</code></p>
<p>
Puis nous créons le fichier ico à partir de plusieurs png de différentes
tailles, 16x16 px, 32x32 px, et 48x48 px. Il serait possible d'utiliser
plus de png, avec différentes profondeurs de couleur par exemple.
</p>
<p><kbd class="code-xterm">icotool -c -o icon.ico icon16.png icon32.png icon48.png</kbd></p>
<p><em>
Vous trouverez un script bash avec cette ligne de commande dans l'archive
example de ce chapitre 3 (dans <code>samples_chapter_3/data/icons/</code>).
</em></p>
<p>
Pour utiliser notre icône pour nos fenêtres, plutôt que celle de firefox
ou de xulrunner, nous avons juste à mettre cette icône, renommée
<code>default.ico</code>, dans le dossier <code>icons/default</code> situé
dans notre dossier chrome principal.
<br />
Cette icône sera utilisée par tous les <code>&lt;window&gt;</code> XUL
sans un attribut <code>id</code>.
<br />
Mais le <code>&lt;window&gt;</code> XUL principal de myapp a l'attribut
<code>id="main"</code>, donc pour cette fenêtre nous devons avoir une
icône nommée <code>main.ico</code>, située dans le même dossier.
</p>
<pre>    |- samples_chapter_3/<br />        |- myapp/<br />            |- chrome<br />                |- icons/<br />                    |- default/<br />                        |- default.ico<br />                        |- main.ico</pre>
</div>
<div class="howto-section">
<h4><span>3.2 Créer un lanceur (batch ou C)</span></h4>
<p>
Le lanceur le plus simple est un <strong>script batch</strong>. Voici le
contenu de <code><strong>myapp.bat</strong></code>&nbsp;:
</p>
<pre>set CUR_DIR=%~dp0<br /><br />START firefox -app $CUR_DIR\application.ini</pre>
<p>
Ce fichier doit être placé dans le dossier principal de notre appli.
Ça marche, il lance notre appli via le fichier application.ini de notre
appli.
<br />
Mais il se passe quelque chose de gênant, une fenêtre noire de commande
est également ouverte.
</p>
<p>
Pour éviter ce defaut, nous allons créer un <strong>lanceur en C</strong>.
</p>
<p>
Nous utiliserons le code de <strong><a href="http://joliclic.free.fr/mozilla/xal/" rel="external">XAL</a></strong>
(XUL Application Launcher). C'est un programme léger en C, sous licence
<a href="http://www.opensource.org/licenses/mit-license.php" rel="external">MIT</a>,
il lance une application XULRunner avec Firefox, avec l'argument <code>-app</code>
et <code>application.ini</code>.
Il doit être placé dans le dossier principal de l'application (comme le batch
précédent). Bonus, il prend en charge d'éventuels arguments supplémentaires
(comme <code>-jsconsole</code>), quand il est utilisé en ligne de commande.
Et nous pouvons ajouter notre icône, et quelques autres informations sur
l'application, via un fichier .rc.
</p>
<p>
Cet exécutable peut etre compilé avec n'importe quel compilateur C, son
code est indépendant du code de Mozilla. Personnellement je le compile
avec <a href="http://www.mingw.org/" rel="external">MinGW</a>, sur Linux,
avec succés.
Si vous voulez utiliser un autre compilateur, éditer le fichier build,
et adapter les variables <code>CC</code> et <code>RESCOMP</code>.
</p>
<p>pour installer MinGW sur Debian/Ubuntu:</p>
<p><code class="code-xterm-root">apt-get install mingw32</code></p>
<p>
Je ne publie pas ici le code source C, vous le trouverez dans l'archive
relative à ce chapitre, où dans sa
<a href="http://joliclic.free.fr/mozilla/xal/en/" rel="external">page dédiée</a>.
</p>
<p>
Nous pouvons <strong>personnaliser</strong> ce lanceur, en utilisant un
fichier
<a href="http://msdn.microsoft.com/en-us/library/aa381043%28v=VS.85%29.aspx" rel="external">resource</a>
(<code>.rc</code>), insérer notre icône et spécifier quelques informations
(vendeur, nom de l'appli, version,...).
</p>
<p>
Voici le contenu du fichier myapp-res.rc&nbsp;:
</p>
<pre>APPLICATION_ICON ICON "myapp.ico"<br /><br />1 VERSIONINFO<br />    FILEVERSION     0,1,0,0<br />    PRODUCTVERSION  0,0,0,0<br />BEGIN<br />    BLOCK "StringFileInfo"<br />    BEGIN<br />        BLOCK "000004B0"<br />        BEGIN<br />            VALUE "Comments", "Published under the MPL 1.1/GPL 2.0/LGPL 2.1 licenses"<br />            VALUE "CompanyName", "John Doe Organization"<br />            VALUE "FileDescription", "MyApp"<br />            VALUE "FileVersion", "1.0.0"<br />            VALUE "InternalName", "MyApp"<br />            VALUE "LegalCopyright", "(c) 2010 John Doe"<br />            VALUE "ProductName", "MyApp"<br />            VALUE "ProductVersion", "0.0.0"<br />        END<br />    END<br />    BLOCK "VarFileInfo"<br />    BEGIN<br />        VALUE "Translation", 0x000, 1200<br />    END<br />END</pre>
<p>Quelques détails sur ce contenu&nbsp;:</p>
<p>
La ligne <code>APPLICATION_ICON <strong>ICON</strong> "myapp.ico"</code>
insère notre icône
</p>
<p>
Les entrées <a href="http://msdn.microsoft.com/en-us/library/aa381058%28v=VS.85%29.aspx" rel="external"><code><strong>FILEVERSION</strong></code>
et <code><strong>PRODUCTVERSION</strong></code></a>
utilisent un format spécial, en résumé
<code>entier virgule entier virgule entier virgule entier</code>.
</p>
<p>
La ligne <code>VALUE "Translation", 0x000, 1200</code> spécifie que les
chaînes (string) utilisées
dans les champs d'information sont en Unicode.
</p>
<p>
Nous pouvons compiler ce lanceur, en utilisant notre fichier resource, avec
le script <code>build.sh</code> fourni avec XAL&nbsp;:
</p>
<p>
<kbd class="code-xterm">sh build.sh myapp myapp-res.rc</kbd>
</p>
<p>
Après compilation, la taille du fichier créé est de ~21Ko, donc vraiment
léger (notez que le poids de l'icône est incluse).
</p>
</div>
<div class="howto-section">
<h4><span>3.3 Créer un script NSIS</span></h4>
<p>
Il existe plusieurs solution pour créer des installeurs pour Windows.
Ici nous utiliserons <a href="http://nsis.sourceforge.net/" rel="external"><strong>NSIS</strong></a>,
car&nbsp;: il est open source, nous pouvons construire notre installeur
depuis Linux, et qu'il est facile et puissant.
<br />
Firefox lui-même utilise NSIS pour son installeur Windows.
</p>
<p>
Pour installer les outils NSIS sur Debian/Ubuntu&nbsp;:
</p>
<p><code class="code-xterm-root">apt-get install nsis</code></p>
<p>
NSIS utilise son propre language de script pour créer les installeurs.
Nous pouvons utiliser des pages par défaut, en créer de nouvelles personnalisées,
gérer les fichiers lors de l'installation/désinstallation, agir sur le Registre
Windows,...
<br />
Je ne vais pas faire une documentation complète sur NSIS ici, voyez leur
<a href="http://nsis.sourceforge.net/Main_Page" rel="external">wiki</a>,
il y a beaucoup d'explications et d'exemples.
<br />
Vous devriez avoir des exemples et une doc disponibles en local, une fois
nsis installé, dans
<code>/usr/share/doc/nsis/Examples</code> et <code>/usr/share/doc/nsis/Doc</code>.
</p>
<p>
Mais voilà le principal script proposé, et j'explique par la suite quelles actions
sont réalisées&nbsp;:
</p>
<pre>!define PRODUCT_NAME "MyApp"<br />!define PRODUCT_INTERNAL_NAME "myapp"<br />!define PRODUCT_VERSION "1.0"<br />!define PRODUCT_WIN_VERSION "1.0.0.0"<br /><br />!define MESSAGEWINDOW_NAME "${PRODUCT_NAME}MessageWindow"<br /><br />!define HKEY_ROOT "HKLM"<br />!define UN_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"<br /><br />!define LICENSE_PATH "${PRODUCT_INTERNAL_NAME}\LICENSE.txt"<br /><br />!define INSTALLER_NAME "${PRODUCT_NAME}-${PRODUCT_VERSION}-install.exe"<br />!define TMP_UNINSTALL_EXE "${PRODUCT_INTERNAL_NAME}_uninstall.exe"<br /><br />;--------------------------------<br />;Variables<br /><br />; The name of the product installed<br />Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"<br /><br />; The file to write<br />OutFile "${INSTALLER_NAME}"<br /><br />SetCompressor /final /solid lzma<br />ShowInstDetails show<br />ShowUninstDetails show<br /><br />; The default installation directory<br />InstallDir $PROGRAMFILES\${PRODUCT_NAME}<br /><br />; Request application privileges for Windows Vista<br />RequestExecutionLevel admin<br /><br />Var Shortcuts_Dialog<br />Var Shortcuts_Label<br />Var Shortcuts_SM_Checkbox<br />Var Shortcuts_SM_Checkbox_State<br />Var Shortcuts_D_Checkbox<br />Var Shortcuts_D_Checkbox_State<br /><br />Var Previous_Uninstall<br />Var Previous_Uninstall_dir<br />Var TempUninstallPath<br /><br />!include "MUI2.nsh"<br />!include "FileFunc.nsh"<br /><br />VIProductVersion "${PRODUCT_WIN_VERSION}"<br /><br />VIAddVersionKey "ProductName"     "${PRODUCT_NAME}"<br />;VIAddVersionKey "CompanyName"     "${CompanyName}"<br />;VIAddVersionKey "LegalTrademarks" "${BrandShortName} is a Trademark of"<br />;VIAddVersionKey "LegalCopyright"  "${CompanyName}"<br />VIAddVersionKey "LegalCopyright"  ""<br />VIAddVersionKey "FileVersion"     "${PRODUCT_VERSION}"<br />VIAddVersionKey "ProductVersion"  "${PRODUCT_VERSION}"<br />VIAddVersionKey "FileDescription" "${PRODUCT_NAME} Installer"<br />VIAddVersionKey "OriginalFilename" "${INSTALLER_NAME}"<br /><br />!define MUI_FINISHPAGE_RUN "$INSTDIR\${PRODUCT_INTERNAL_NAME}.exe"<br /><br />;--------------------------------<br />; Pages<br /><br />    !insertmacro MUI_PAGE_WELCOME<br />    !insertmacro MUI_PAGE_LICENSE "${LICENSE_PATH}"<br />    !insertmacro MUI_PAGE_DIRECTORY<br />    Page custom onShortcutsPageCreate<br />    !insertmacro MUI_PAGE_INSTFILES<br />    !insertmacro MUI_PAGE_FINISH<br />    <br />    !insertmacro MUI_UNPAGE_WELCOME<br />    !insertmacro MUI_UNPAGE_CONFIRM<br />    !insertmacro MUI_UNPAGE_INSTFILES<br />    <br />    <br />    !insertmacro MUI_LANGUAGE "English"<br />    !insertmacro MUI_LANGUAGE "French"<br /><br />    !include ./l10n/fr.nsh<br />    !include ./l10n/en_US.nsh<br /><br /><br />;--------------------------------<br /><br />Function .onInit<br />    ; an eventual previous version of the app should not be currently running.<br />    ; Abort if any.<br />    ; Explanation, when the application is running, a window with the className<br />    ; productnameMessageWindow exists<br />    FindWindow $0 "${MESSAGEWINDOW_NAME}"<br />    StrCmp $0 0 +3<br />        MessageBox MB_OK|MB_ICONEXCLAMATION "${PRODUCT_NAME} is running. Please close it first" /SD IDOK<br />        Abort<br />    <br />    StrCpy $Shortcuts_SM_Checkbox_State 1<br />    StrCpy $Shortcuts_D_Checkbox_State 1<br />FunctionEnd<br /><br />Function un.onInit<br />    ; see Function .onInit<br />    FindWindow $0 "${MESSAGEWINDOW_NAME}"<br />    StrCmp $0 0 +3<br />        MessageBox MB_OK|MB_ICONEXCLAMATION "${PRODUCT_NAME} is running. Please close it first" /SD IDOK<br />        Abort<br />FunctionEnd<br /><br />; custom page creation, for the shortcuts installation, using nsDialog<br />Function onShortcutsPageCreate<br />    !insertmacro MUI_HEADER_TEXT $(l10n_SHORTCUTS_PAGE_TITLE) \<br />        $(l10n_SHORTCUTS_PAGE_SUBTITLE)<br />    <br />    nsDialogs::Create 1018<br />    Pop $Shortcuts_Dialog<br />    <br />    ${If} $Shortcuts_Dialog == error<br />        Abort<br />    ${EndIf}<br /><br />    ${NSD_CreateLabel} 0 6 100% 12u $(l10n_CREATE_ICONS_DESC)<br />    Pop $Shortcuts_Label<br /><br />    ${NSD_CreateCheckbox} 15u 20u 100% 10u $(l10n_ICONS_STARTMENU)<br />    Pop $Shortcuts_SM_Checkbox<br />    GetFunctionAddress $0 OnSMCheckbox<br />    nsDialogs::OnClick $Shortcuts_SM_Checkbox $0<br />    <br />    ${If} $Shortcuts_SM_Checkbox_State == ${BST_CHECKED}<br />        ${NSD_Check} $Shortcuts_SM_Checkbox<br />    ${EndIf}<br /><br />    ${NSD_CreateCheckbox} 15u 40u 100% 10u $(l10n_ICONS_DESKTOP)<br />    Pop $Shortcuts_D_Checkbox<br />    GetFunctionAddress $0 OnDCheckbox<br />    nsDialogs::OnClick $Shortcuts_D_Checkbox $0<br /><br />    ${If} $Shortcuts_D_Checkbox_State == ${BST_CHECKED}<br />        ${NSD_Check} $Shortcuts_D_Checkbox<br />    ${EndIf}<br /><br />    nsDialogs::Show<br />FunctionEnd<br /><br />; event when the Start Menu shortcut is (un)checked in the custom page<br />Function OnSMCheckbox<br />    ${NSD_GetState} $Shortcuts_SM_Checkbox $Shortcuts_SM_Checkbox_State<br />    Pop $0 # HWND<br />FunctionEnd<br /><br />; event when the Desktop shortcut is (un)checked in the custom page<br />Function OnDCheckbox<br />    ${NSD_GetState} $Shortcuts_D_Checkbox $Shortcuts_D_Checkbox_State<br />    Pop $0 # HWND<br />FunctionEnd<br /><br />Function WriteUninstallReg<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "DisplayName" \<br />        "${PRODUCT_NAME} (${PRODUCT_VERSION})"<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "UninstallString" \<br />        "$INSTDIR\uninstall.exe"<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "QuietUninstallString" \<br />        "$INSTDIR\uninstall.exe /S"<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "InstallLocation" \<br />        "$INSTDIR"<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "DisplayIcon" \<br />        "$INSTDIR\${PRODUCT_INTERNAL_NAME}.exe"<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "DisplayVersion" \<br />        "${PRODUCT_VERSION}"<br />    <br />    ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2<br />    IntFmt $0 "0x%08X" $0<br />    WriteRegDWORD ${HKEY_ROOT} ${UN_KEY} "EstimatedSize" "$0"<br />FunctionEnd<br /><br />; The stuff to install<br />Section ""<br />    ; uninstall an eventual previous installation<br />    ReadRegStr $Previous_Uninstall ${HKEY_ROOT} ${UN_KEY} "UninstallString"<br />    ClearErrors<br />    ${If} $Previous_Uninstall != ""<br />        StrCpy $Previous_Uninstall_dir $Previous_Uninstall<br />        ${GetParent} $Previous_Uninstall $Previous_Uninstall_dir<br />        <br />        IfFileExists "$Previous_Uninstall" myUninstallPrevious myInstall<br />    ${Else}<br />        goto myInstall<br />    ${EndIf}<br />  <br />    myUninstallPrevious:<br />        ; copy the previous uninstaller into TEMP<br />        ClearErrors<br />        StrCpy $TempUninstallPath "$TEMP\${TMP_UNINSTALL_EXE}"<br />        CopyFiles /SILENT "$Previous_Uninstall" "$TempUninstallPath"<br />        IfErrors myInstall<br />        <br />        ClearErrors<br />        ExecWait '"$TempUninstallPath" /S _?=$Previous_Uninstall_dir'<br />        <br />        ClearErrors<br />        Delete "$TempUninstallPath"<br />        <br />        ;MessageBox MB_OK "UNINSTALL: finished"<br />    <br />    myInstall:<br />        SetOutPath $INSTDIR<br />        <br />        ; copy the files<br />        File /r ${PRODUCT_INTERNAL_NAME}\*<br />        <br />        WriteUninstaller "uninstall.exe"<br />        <br />        Call WriteUninstallReg<br />    <br />        ${If} $Shortcuts_SM_Checkbox_State == ${BST_CHECKED}<br />            CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}.lnk" \<br />                "$INSTDIR\${PRODUCT_INTERNAL_NAME}.exe"<br />        ${EndIf}<br />        <br />        ${If} $Shortcuts_D_Checkbox_State == ${BST_CHECKED}<br />            CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" \<br />                "$INSTDIR\${PRODUCT_INTERNAL_NAME}.exe"<br />        ${EndIf}<br />SectionEnd<br /><br />;--------------------------------<br />; Uninstaller<br /><br />Section "Uninstall"<br />    MessageBox MB_OK|MB_ICONEXCLAMATION "$INSTDIR" /SD IDOK<br />    ; Remove installed files and uninstaller<br />    !include ./uninstall_files.nsi<br />    Delete "$INSTDIR\uninstall.exe"<br />    <br />    ; remove installed directories<br />    !include ./uninstall_dirs.nsi<br />    RMDir /r "$INSTDIR\extensions"<br />    <br />    ; Remove shortcuts, if any<br />    Delete "$SMPROGRAMS\${PRODUCT_NAME}.lnk"<br />    Delete "$DESKTOP\${PRODUCT_NAME}.lnk"<br />    ;TODO remove eventual quicklaunch Too<br />    <br />    ; Remove the installation directory used (if empty)<br />    RMDir "$INSTDIR"<br />  <br />    ; and delete the registry key for uninstall<br />    DeleteRegKey ${HKEY_ROOT} ${UN_KEY}<br />SectionEnd</pre>
<p>Quelques explications sur ce script&nbsp;:</p>
<p>Il utilise le thème par défaut "modern". Mais il serait possible de le personnaliser.</p>
<p>
Certaines parties sont localisées ("traduites"), en insérant d'autres
scripts nsis (décrits plus loin).
</p>
<p>
Il utilise quelques pages nsis par défaut, et une personnalisée pour la création
des raccourcis sur le bureau et dans le menu démarrez.
</p>
<p>
L'installation et la désinstallation sont annulées si notre application est
actuellement lancée.
<br />
En fait, quand notre application est en fonctionnement, XULRunner/Firefox crée
une fenêtre Windows native avec une classe <code>MyAppMessageWindow</code>,
le nom de cette classe est la valeur du champ <code>Name</code>
dans <code>application.ini</code> concaténée avec "MessageWindow".
<br />
Le script vérifie juste si une telle fenêtre avec ce nom de classe est ouverte,
et annule le traitement.
</p>
<p>
Il crée quelques entrées minimales dans La Base de Registre, pour permettre
la désinstallation du programme avec l'outil "ajouter/supprimer des programmes"
de Windows.
</p>
<p>
Si notre appli est déjà installée, la précédente version est désinstallée
avant la nouvelle installation, en utilisant le désinstalleur précédent.
Et, pour être plus précis, ce précédent désinstalleur est copié et lancé
depuis le dossier "Temp" de Windows.
</p>
<p>
Pour la désinstallation, nous avons besoin de la liste complète des fichiers
et dossiers installés.
Ces listes seront créés dynamiquement plus tard, pour le moment dans ce script
nous les insérons en tant que scripts nsis supplémentaires
(<code>uninstall_files.nsi</code> et <code>uninstall_dirs.nsi</code>).
</p>
<p>
Maintenant voici le contenu de l'un des scripts localisés ("traduit"), en_US.nsh&nbsp;:
</p>
<pre>;!!! IMPORTANT: this must file must be edited with ANSI charset (in fact the<br />; Windows CP-1252 charset), but if there's no special character, UTF-8 is ok,<br />; because it's a subset ;)<br /><br />LangString l10n_SHORTCUTS_PAGE_TITLE ${LANG_ENGLISH} \<br />    "Set Up Shortcuts"<br />LangString l10n_SHORTCUTS_PAGE_SUBTITLE ${LANG_ENGLISH} \<br />    "Create Program Icons"<br />LangString l10n_CREATE_ICONS_DESC ${LANG_ENGLISH} \<br />    "Create icons for ${PRODUCT_NAME}:"<br />LangString l10n_ICONS_DESKTOP ${LANG_ENGLISH} \<br />    "On my &amp;Desktop"<br />LangString l10n_ICONS_STARTMENU ${LANG_ENGLISH} \<br />    "In my &amp;Start Menu Programs folder"</pre>
<p>
Nous devons faire attention à l'encodage des ces fichiers, celui-ci en anglais
ne devrait pas poser de problème, mais celui en français doit être édité
avec le charset Windows <code>CP-1252</code> par exemple.
Ces variables sont utilisées simplement dans notre script principal avec,
par exemple, <code>$(l10n_SHORTCUTS_PAGE_TITLE)</code>.
</p>
<p>
Notez que l'esperluette <code>&amp;</code> dans les définitions de chaîne
définissent des raccourcis clavier pour les contrôles dans l'interface
utilisateur, ici il y a <code>alt+D</code> et <code>alt+S</code>.
</p>
</div>
<div class="howto-section">
<h4><span>3.4 Créer l'installeur</span></h4>
<p>
Nous avons maintenant tous les fichiers pour créer l'installeur.
Voyons l'arborescence de nos sources&nbsp;:
</p>
<pre>    |-samples_chapter_3<br />        |- data/<br />            |- icons/<br />                |- icon.ico<br />            |- myapp.bat<br />            |- myapp-res.rc<br />        |- myapp/<br />        |- win<br />            |- nsis/<br />                |- l10n/<br />                    |- en_US.nsh<br />                    |- fr.nsh<br />                |- myapp.nsi<br />            |- xal-src/<br />                |- build.sh<br />                |- clean.sh<br />                |- main.c</pre>
<p>
Nous devons construire notre lanceur à partir des sources C et de nos
données (icône et resource).
Et créer 2 scripts nsis additionnels, pour lister les fichiers de notre appli.
Puis nous pourrons créer notre installeur avec <code>makensis</code>.
Nous allons faire celà dans un dossier temporaire. Voici le script, nommé
<code>build_win.sh</code>&nbsp;:
</p>
<pre>#!/bin/bash<br /><br /># exit the script on errors<br />set -e<br /><br />TMP_DIR=./tmp<br /><br /># get the absolute path of our TMP_DIR folder<br />TMP_DIR=$(readlink -f -- "$TMP_DIR")<br /><br /># re-create the TMP_DIR folder<br />rm -rfv "$TMP_DIR"<br />mkdir -v "$TMP_DIR"<br /><br /># copy our app<br />cp -rv myapp "$TMP_DIR/"<br /><br /># copy the XAL launcher sources<br />cp -rv win/xal-src "$TMP_DIR/xal"<br /># and our icon and resource file<br />cp -v data/icons/icon.ico "$TMP_DIR/xal/myapp.ico"<br />cp -v data/myapp-res.rc "$TMP_DIR/xal/"<br /><br /># build the launcher<br />cd "$TMP_DIR/xal/"<br />sh build.sh myapp myapp-res.rc<br />cd -<br /><br /># copy the launchers in the right folder<br />cp -v data/myapp.bat "$TMP_DIR/myapp/"<br />cp -v "$TMP_DIR/xal/myapp.exe" "$TMP_DIR/myapp/"<br /><br /># delete the xal sources<br />rm -rv "$TMP_DIR/xal"<br /><br /># create the nsis script listing the files to unsinstall<br />cd "$TMP_DIR/myapp"<br />find . -maxdepth 1 -type f &gt; ../uninstall_files.nsi<br />sed -i -r "s|^\./(.*)$|  Delete \"\$INSTDIR\\\\\1\"|" ../uninstall_files.nsi<br /><br /># and the list of directory<br />ls -d */ &gt; ../uninstall_dirs.nsi<br />sed -i -r "s|^(.*)/$|  RMDir /r \"\$INSTDIR\\\\\1\"|" ../uninstall_dirs.nsi<br />cd -<br /><br /># copy the other nsis scripts<br />cp -rv win/nsis/* "$TMP_DIR/"<br /><br /># and create the installer<br />makensis "$TMP_DIR/myapp.nsi"<br /><br /># finally, copy our installer in the root sources dir<br />cp -v "$TMP_DIR/MyApp-1.0-install.exe" ./<br /><br />echo "Windows installer for myapp created."</pre>
<p>Pour lancer ce script, dans un terminal&nbsp;:</p>
<ul class="code-xterm">
<li><pre>cd samples_chapter_3</pre></li>
<li><pre>sh ./build_win.sh</pre></li>
</ul>
<p>
Et en résultat nous avons finalement le fichier
<code>MyApp-1.0-install.exe</code> dans le dossier
<code>samples_chapter_3</code> :) .
</p>
</div>
<div class="howto-navigator-bottom">
<div class="howto-previous"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribuer-votre-appli-XULRunner-24-Empaqueter-un-rpm" title="Aller au chapitre 2.4">&lt; chapitre précédent</a></div>
<div class="howto-next"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribuer-votre-appli-XULRunner-4-Mac-OSX" title="Aller au chapitre 4">chapitre suivant &gt;</a></div>
<div class="clearer">&nbsp;</div>
</div>
<div class="howto-author">
<p>Nicolas Martin</p>
</div>
<div class="howto-download-section">
<p>
Vous pouvez télécharger tous les exemples de ce chapitre 3 (Windows) dans l'archive
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/dl.php?id=current_sample_3" class="howto-download-archive">
samples_chapter_3.tar.gz
</a>.
</p>
</div>
<div class="howto-credits">
<p><em>
L'application myapp, de
<a href="https://developer.mozilla.org/en/getting_started_with_xulrunner" rel="external">developer.mozilla.org</a>,
est dans le <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domaine Public</a>.
</em></p>
<p><em>
L'icône utilisée est issue du
<a href="http://tango.freedesktop.org" rel="external">Tango Desktop Project</a>,
et est dans le <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domaine Public</a>.
</em></p>
<p><em>
le lanceur C
<a href="http://joliclic.free.fr/mozilla/xal/en/" rel="external">XUL App Launcher</a> (XAL)
est sous <a href="http://www.opensource.org/licenses/mit-license.php" rel="external">licence MIT</a>.
</em></p>
<p><em>
Toutes les autres données ajoutées, et les fichiers en exemple, de ce chapitre 3, sont dans le
<a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domain Public</a> également.
</em></p>
</div>
<div class="howto-footer">
<p>
Le contenu de cet article est sous les termes de la licence
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>
</p>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width: 0;" src="http://i.creativecommons.org/l/by-sa/3.0/80x15.png" /></a>
</div>
</div>]]></content:encoded>
</item>
     <item rdf:about="http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribute-your-XULRunner-app-3-Windows">
    <title>Distribute your XULRunner app - 3 - Windows</title>
    <link>http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribute-your-XULRunner-app-3-Windows</link>
    <dc:date>2011-05-25T12:25:00+00:00</dc:date>
    <dc:language>fr</dc:language>
    <dc:creator>Joliclic blog - mozilla</dc:creator>
    <dc:subject></dc:subject>
	<description></description>
	<content:encoded><![CDATA[    <div class="howto">
<p><em>Ce billet existe aussi en <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribuer-votre-appli-XULRunner-3-Windows">français</a></em></p>
<p><em>
This post is part of a <a href="http://joliclic.free.fr/blog/index.php?tag/dist_xul_app_en">series</a> about how to package a XULRunner application.<br />
See the <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/20/Distribute-your-XULRunner-app-1-Preamble">preamble</a> for the context case.
</em></p>
<h3><span>3 - Windows</span></h3>
<ul>
<li>3.1 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/#howto_dxr_3.1">Icons for Windows</a></li>
<li>3.2 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/#howto_dxr_3.2">Create a launcher (batch or C)</a></li>
<li>3.3 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/#howto_dxr_3.3">Create a NSIS script</a></li>
<li>3.4 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/#howto_dxr_3.4">Create the installer</a></li>
</ul>
<div class="howto-section">
<h4><span>3.1 Icons for Windows</span></h4>
<p>
We need a icon in .ico format. It will be used by ours windows, and by
our launcher.
</p>
<p>
It's easy to make a .ico file on Linux, we just need to install the
program <code>icotool</code>, from the <code>icoutils</code> package.
<br />
On Debian/Ubuntu:
</p>
<p><code class="code-xterm-root">apt-get install icoutils</code></p>
<p>
Then we create a ico file from several png at different size,
16x16 px, 32x32 px, and 48x48 px. It would be possible to add more png,
with different color depth as well.
</p>
<p><kbd class="code-xterm">icotool -c -o icon.ico icon16.png icon32.png icon48.png</kbd></p>
<p><em>
You can find a bash script with this command line in the sample archive
related to this chapter 3 (in <code>samples_chapter_3/data/icons/</code>).
</em></p>
<p>
To add our icon to our windows, rather than the firefox or xulrunner one,
we have just to put this icon, renamed as <code>default.ico</code>, into a
<code>icons/default</code> folder situated in our main chrome folder.
<br />
This icon will be used by all XUL <code>&lt;window&gt;</code> without an
<code>id</code> attribute.
<br />
But the main XUL <code>&lt;window&gt;</code> of myapp has the attribute
<code>id="main"</code>, so for this window we must have an icon named
<code>main.ico</code>, situated in the same folder:
</p>
<pre>    |- samples_chapter_3/<br />        |- myapp/<br />            |- chrome<br />                |- icons/<br />                    |- default/<br />                        |- default.ico<br />                        |- main.ico</pre>
</div>
<div class="howto-section">
<h4><span>3.2 Create a launcher (batch or C)</span></h4>
<p>
The simplest launcher is a <strong>batch script</strong>. Here the content
of <code><strong>myapp.bat</strong></code>:
</p>
<pre>set CUR_DIR=%~dp0<br /><br />START firefox -app $CUR_DIR\application.ini</pre>
<p>
This file must be placed into the main folder of our app.
This works, it launches our app via the application.ini file of our app.
<br />
But there's something annoying, a black command window is opened too.
</p>
<p>
To avoid the previously mentioned default, we will create a
<strong>launcher in C</strong>.
</p>
<p>
We use the code of <strong><a href="http://joliclic.free.fr/mozilla/xal/en/" rel="external">XAL</a></strong>
(XUL Application Launcher). This is a light C program,
<a href="http://www.opensource.org/licenses/mit-license.php" rel="external">MIT</a>
licensed, it launches
a XULRunner application with Firefox, with the <code>-app</code> argument and the
<code>application.ini</code>.
It must be placed in the main application folder (like the previous batch).
Bonus, it handles additional arguments (like <code>-jsconsole</code>) if
used in command line. And we can add our icon, and some application
information via a .rc file.
</p>
<p>
This executable can be compiled with any C compiler, its code is
independent of the Mozilla code. I personaly compile it with
<a href="http://www.mingw.org/" rel="external">MinGW</a>, on Linux, with
success. If you plan to use another compiler, edit the build file, and
adapt the <code>CC</code> and <code>RESCOMP</code> variables.
</p>
<p>To install MinGW on Debian/Ubuntu:</p>
<p><code class="code-xterm-root">apt-get install mingw32</code></p>
<p>
I don't publish here the C source of this code, you'll find it in the
archive related to this chapter 3, or in its
<a href="http://joliclic.free.fr/mozilla/xal/en/" rel="external">dedicated page</a>.
</p>
<p>
We can <strong>customize</strong> this launcher, using a
<a href="http://msdn.microsoft.com/en-us/library/aa381043%28v=VS.85%29.aspx" rel="external">resource</a>
(<code>.rc</code>) file, insert our icon and specify some
information (vendor, app name, version,...).
</p>
<p>
Here the content of the myapp-res.rc file:
</p>
<pre>APPLICATION_ICON ICON "myapp.ico"<br /><br />1 VERSIONINFO<br />    FILEVERSION     0,1,0,0<br />    PRODUCTVERSION  0,0,0,0<br />BEGIN<br />    BLOCK "StringFileInfo"<br />    BEGIN<br />        BLOCK "000004B0"<br />        BEGIN<br />            VALUE "Comments", "Published under the MPL 1.1/GPL 2.0/LGPL 2.1 licenses"<br />            VALUE "CompanyName", "John Doe Organization"<br />            VALUE "FileDescription", "MyApp"<br />            VALUE "FileVersion", "1.0.0"<br />            VALUE "InternalName", "MyApp"<br />            VALUE "LegalCopyright", "(c) 2010 John Doe"<br />            VALUE "ProductName", "MyApp"<br />            VALUE "ProductVersion", "0.0.0"<br />        END<br />    END<br />    BLOCK "VarFileInfo"<br />    BEGIN<br />        VALUE "Translation", 0x000, 1200<br />    END<br />END</pre>
<p>Some details about this content:</p>
<p>
The line <code>APPLICATION_ICON <strong>ICON</strong> "myapp.ico"</code>
integrate our icon
</p>
<p>
The <a href="http://msdn.microsoft.com/en-us/library/aa381058%28v=VS.85%29.aspx" rel="external"><code><strong>FILEVERSION</strong></code> and <code><strong>PRODUCTVERSION</strong></code></a>
entries use a special format, in short <code>integer comma integer comma integer comma integer</code>.
</p>
<p>
The line <code>VALUE "Translation", 0x000, 1200</code> specify that the
strings for information use Unicode.
</p>
<p>
We can compile this launcher, using our resource file, with the
<code>build.sh</code> script distributed with XAL:
</p>
<p>
<kbd class="code-xterm">sh build.sh myapp myapp-res.rc</kbd>
</p>
<p>
After compilation, the size of the result file is ~21Kb, so very small
(note that the size of the icon is included).
</p>
</div>
<div class="howto-section">
<h4><span>3.3 Create a NSIS script</span></h4>
<p>
There are several solution to create Windows installers. Here, we will
use <a href="http://nsis.sourceforge.net/" rel="external"><strong>NSIS</strong></a>,
because: it's open source, we can build our installer from Linux, and
it's easy and powerful.
<br />
Firefox itself use NSIS for its Windows installer.
</p>
<p>
To install NSIS tools on Debian/Ubuntu:
</p>
<p><code class="code-xterm-root">apt-get install nsis</code></p>
<p>
NSIS uses its own script language to create installers.
We can use some default pages, create some custom ones, manage files (un)installation,
act on the Windows Registry,...
<br />
I will not do a complete NSIS documentation here, see their
<a href="http://nsis.sourceforge.net/Main_Page" rel="external">wiki</a> for that,
there's a lot of explanations and examples.
<br />
You should have some local examples and doc after installing nsis,
in <code>/usr/share/doc/nsis/Examples</code> and <code>/usr/share/doc/nsis/Doc</code>.
</p>
<p>
But here's the main proposed script here, and I will explain what actions
are performed after:
</p>
<pre>!define PRODUCT_NAME "MyApp"<br />!define PRODUCT_INTERNAL_NAME "myapp"<br />!define PRODUCT_VERSION "1.0"<br />!define PRODUCT_WIN_VERSION "1.0.0.0"<br /><br />!define MESSAGEWINDOW_NAME "${PRODUCT_NAME}MessageWindow"<br /><br />!define HKEY_ROOT "HKLM"<br />!define UN_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"<br /><br />!define LICENSE_PATH "${PRODUCT_INTERNAL_NAME}\LICENSE.txt"<br /><br />!define INSTALLER_NAME "${PRODUCT_NAME}-${PRODUCT_VERSION}-install.exe"<br />!define TMP_UNINSTALL_EXE "${PRODUCT_INTERNAL_NAME}_uninstall.exe"<br /><br />;--------------------------------<br />;Variables<br /><br />; The name of the product installed<br />Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"<br /><br />; The file to write<br />OutFile "${INSTALLER_NAME}"<br /><br />SetCompressor /final /solid lzma<br />ShowInstDetails show<br />ShowUninstDetails show<br /><br />; The default installation directory<br />InstallDir $PROGRAMFILES\${PRODUCT_NAME}<br /><br />; Request application privileges for Windows Vista<br />RequestExecutionLevel admin<br /><br />Var Shortcuts_Dialog<br />Var Shortcuts_Label<br />Var Shortcuts_SM_Checkbox<br />Var Shortcuts_SM_Checkbox_State<br />Var Shortcuts_D_Checkbox<br />Var Shortcuts_D_Checkbox_State<br /><br />Var Previous_Uninstall<br />Var Previous_Uninstall_dir<br />Var TempUninstallPath<br /><br />!include "MUI2.nsh"<br />!include "FileFunc.nsh"<br /><br />VIProductVersion "${PRODUCT_WIN_VERSION}"<br /><br />VIAddVersionKey "ProductName"     "${PRODUCT_NAME}"<br />;VIAddVersionKey "CompanyName"     "${CompanyName}"<br />;VIAddVersionKey "LegalTrademarks" "${BrandShortName} is a Trademark of"<br />;VIAddVersionKey "LegalCopyright"  "${CompanyName}"<br />VIAddVersionKey "LegalCopyright"  ""<br />VIAddVersionKey "FileVersion"     "${PRODUCT_VERSION}"<br />VIAddVersionKey "ProductVersion"  "${PRODUCT_VERSION}"<br />VIAddVersionKey "FileDescription" "${PRODUCT_NAME} Installer"<br />VIAddVersionKey "OriginalFilename" "${INSTALLER_NAME}"<br /><br />!define MUI_FINISHPAGE_RUN "$INSTDIR\${PRODUCT_INTERNAL_NAME}.exe"<br /><br />;--------------------------------<br />; Pages<br /><br />    !insertmacro MUI_PAGE_WELCOME<br />    !insertmacro MUI_PAGE_LICENSE "${LICENSE_PATH}"<br />    !insertmacro MUI_PAGE_DIRECTORY<br />    Page custom onShortcutsPageCreate<br />    !insertmacro MUI_PAGE_INSTFILES<br />    !insertmacro MUI_PAGE_FINISH<br />    <br />    !insertmacro MUI_UNPAGE_WELCOME<br />    !insertmacro MUI_UNPAGE_CONFIRM<br />    !insertmacro MUI_UNPAGE_INSTFILES<br />    <br />    <br />    !insertmacro MUI_LANGUAGE "English"<br />    !insertmacro MUI_LANGUAGE "French"<br /><br />    !include ./l10n/fr.nsh<br />    !include ./l10n/en_US.nsh<br /><br /><br />;--------------------------------<br /><br />Function .onInit<br />    ; an eventual previous version of the app should not be currently running.<br />    ; Abort if any.<br />    ; Explanation, when the application is running, a window with the className<br />    ; productnameMessageWindow exists<br />    FindWindow $0 "${MESSAGEWINDOW_NAME}"<br />    StrCmp $0 0 +3<br />        MessageBox MB_OK|MB_ICONEXCLAMATION "${PRODUCT_NAME} is running. Please close it first" /SD IDOK<br />        Abort<br />    <br />    StrCpy $Shortcuts_SM_Checkbox_State 1<br />    StrCpy $Shortcuts_D_Checkbox_State 1<br />FunctionEnd<br /><br />Function un.onInit<br />    ; see Function .onInit<br />    FindWindow $0 "${MESSAGEWINDOW_NAME}"<br />    StrCmp $0 0 +3<br />        MessageBox MB_OK|MB_ICONEXCLAMATION "${PRODUCT_NAME} is running. Please close it first" /SD IDOK<br />        Abort<br />FunctionEnd<br /><br />; custom page creation, for the shortcuts installation, using nsDialog<br />Function onShortcutsPageCreate<br />    !insertmacro MUI_HEADER_TEXT $(l10n_SHORTCUTS_PAGE_TITLE) \<br />        $(l10n_SHORTCUTS_PAGE_SUBTITLE)<br />    <br />    nsDialogs::Create 1018<br />    Pop $Shortcuts_Dialog<br />    <br />    ${If} $Shortcuts_Dialog == error<br />        Abort<br />    ${EndIf}<br /><br />    ${NSD_CreateLabel} 0 6 100% 12u $(l10n_CREATE_ICONS_DESC)<br />    Pop $Shortcuts_Label<br /><br />    ${NSD_CreateCheckbox} 15u 20u 100% 10u $(l10n_ICONS_STARTMENU)<br />    Pop $Shortcuts_SM_Checkbox<br />    GetFunctionAddress $0 OnSMCheckbox<br />    nsDialogs::OnClick $Shortcuts_SM_Checkbox $0<br />    <br />    ${If} $Shortcuts_SM_Checkbox_State == ${BST_CHECKED}<br />        ${NSD_Check} $Shortcuts_SM_Checkbox<br />    ${EndIf}<br /><br />    ${NSD_CreateCheckbox} 15u 40u 100% 10u $(l10n_ICONS_DESKTOP)<br />    Pop $Shortcuts_D_Checkbox<br />    GetFunctionAddress $0 OnDCheckbox<br />    nsDialogs::OnClick $Shortcuts_D_Checkbox $0<br /><br />    ${If} $Shortcuts_D_Checkbox_State == ${BST_CHECKED}<br />        ${NSD_Check} $Shortcuts_D_Checkbox<br />    ${EndIf}<br /><br />    nsDialogs::Show<br />FunctionEnd<br /><br />; event when the Start Menu shortcut is (un)checked in the custom page<br />Function OnSMCheckbox<br />    ${NSD_GetState} $Shortcuts_SM_Checkbox $Shortcuts_SM_Checkbox_State<br />    Pop $0 # HWND<br />FunctionEnd<br /><br />; event when the Desktop shortcut is (un)checked in the custom page<br />Function OnDCheckbox<br />    ${NSD_GetState} $Shortcuts_D_Checkbox $Shortcuts_D_Checkbox_State<br />    Pop $0 # HWND<br />FunctionEnd<br /><br />Function WriteUninstallReg<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "DisplayName" \<br />        "${PRODUCT_NAME} (${PRODUCT_VERSION})"<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "UninstallString" \<br />        "$INSTDIR\uninstall.exe"<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "QuietUninstallString" \<br />        "$INSTDIR\uninstall.exe /S"<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "InstallLocation" \<br />        "$INSTDIR"<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "DisplayIcon" \<br />        "$INSTDIR\${PRODUCT_INTERNAL_NAME}.exe"<br />    WriteRegStr ${HKEY_ROOT} ${UN_KEY} "DisplayVersion" \<br />        "${PRODUCT_VERSION}"<br />    <br />    ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2<br />    IntFmt $0 "0x%08X" $0<br />    WriteRegDWORD ${HKEY_ROOT} ${UN_KEY} "EstimatedSize" "$0"<br />FunctionEnd<br /><br />; The stuff to install<br />Section ""<br />    ; uninstall an eventual previous installation<br />    ReadRegStr $Previous_Uninstall ${HKEY_ROOT} ${UN_KEY} "UninstallString"<br />    ClearErrors<br />    ${If} $Previous_Uninstall != ""<br />        StrCpy $Previous_Uninstall_dir $Previous_Uninstall<br />        ${GetParent} $Previous_Uninstall $Previous_Uninstall_dir<br />        <br />        IfFileExists "$Previous_Uninstall" myUninstallPrevious myInstall<br />    ${Else}<br />        goto myInstall<br />    ${EndIf}<br />  <br />    myUninstallPrevious:<br />        ; copy the previous uninstaller into TEMP<br />        ClearErrors<br />        StrCpy $TempUninstallPath "$TEMP\${TMP_UNINSTALL_EXE}"<br />        CopyFiles /SILENT "$Previous_Uninstall" "$TempUninstallPath"<br />        IfErrors myInstall<br />        <br />        ClearErrors<br />        ExecWait '"$TempUninstallPath" /S _?=$Previous_Uninstall_dir'<br />        <br />        ClearErrors<br />        Delete "$TempUninstallPath"<br />        <br />        ;MessageBox MB_OK "UNINSTALL: finished"<br />    <br />    myInstall:<br />        SetOutPath $INSTDIR<br />        <br />        ; copy the files<br />        File /r ${PRODUCT_INTERNAL_NAME}\*<br />        <br />        WriteUninstaller "uninstall.exe"<br />        <br />        Call WriteUninstallReg<br />    <br />        ${If} $Shortcuts_SM_Checkbox_State == ${BST_CHECKED}<br />            CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}.lnk" \<br />                "$INSTDIR\${PRODUCT_INTERNAL_NAME}.exe"<br />        ${EndIf}<br />        <br />        ${If} $Shortcuts_D_Checkbox_State == ${BST_CHECKED}<br />            CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" \<br />                "$INSTDIR\${PRODUCT_INTERNAL_NAME}.exe"<br />        ${EndIf}<br />SectionEnd<br /><br />;--------------------------------<br />; Uninstaller<br /><br />Section "Uninstall"<br />    MessageBox MB_OK|MB_ICONEXCLAMATION "$INSTDIR" /SD IDOK<br />    ; Remove installed files and uninstaller<br />    !include ./uninstall_files.nsi<br />    Delete "$INSTDIR\uninstall.exe"<br />    <br />    ; remove installed directories<br />    !include ./uninstall_dirs.nsi<br />    RMDir /r "$INSTDIR\extensions"<br />    <br />    ; Remove shortcuts, if any<br />    Delete "$SMPROGRAMS\${PRODUCT_NAME}.lnk"<br />    Delete "$DESKTOP\${PRODUCT_NAME}.lnk"<br />    ;TODO remove eventual quicklaunch Too<br />    <br />    ; Remove the installation directory used (if empty)<br />    RMDir "$INSTDIR"<br />  <br />    ; and delete the registry key for uninstall<br />    DeleteRegKey ${HKEY_ROOT} ${UN_KEY}<br />SectionEnd</pre>
<p>Some descriptions about this script:</p>
<p>It uses the default "modern" skin. But it's possible to customize it.</p>
<p>
It uses some localized parts, including some other nsis scripts (described later).
</p>
<p>
It uses some default nsis pages, and a custom one to allow the creation of
shortcuts on the desktop and in the start menu.
</p>
<p>
The installation and uninstallation are aborted if our application is currently running.
<br />
In fact, when our app is running, XULRunner/Firefox create a native Windows window with
a class <code>MyAppMessageWindow</code>, this class name is the value of the field
<code>Name</code> of the <code>application.ini</code> concatenated with "MessageWindow".
<br />
The script just checks if such a window with this class name is opened, then abort.
</p>
<p>
It creates some minimal Registry entries to allow the uninstallation of the app
with the "add/remove programs" tool.
</p>
<p>
If our app is already installed, the previous version is uninstalled before the new
installation, using our previous uninstaller. And, to be more precise,
this previous uninstaller is copied and launched from the Windows temp folder.
</p>
<p>
For the uninstaller, we need the complete list of installed files and directories.
These lists will be dynamically created later, for the moment in this script we
just include them as other nsis scripts (<code>uninstall_files.nsi</code>
and <code>uninstall_dirs.nsi</code>).
</p>
<p>
Now here the content of one of the localized included script, en_US.nsh:
</p>
<pre>;!!! IMPORTANT: this must file must be edited with ANSI charset (in fact the<br />; Windows CP-1252 charset), but if there's no special character, UTF-8 is ok,<br />; because it's a subset ;)<br /><br />LangString l10n_SHORTCUTS_PAGE_TITLE ${LANG_ENGLISH} \<br />    "Set Up Shortcuts"<br />LangString l10n_SHORTCUTS_PAGE_SUBTITLE ${LANG_ENGLISH} \<br />    "Create Program Icons"<br />LangString l10n_CREATE_ICONS_DESC ${LANG_ENGLISH} \<br />    "Create icons for ${PRODUCT_NAME}:"<br />LangString l10n_ICONS_DESKTOP ${LANG_ENGLISH} \<br />    "On my &amp;Desktop"<br />LangString l10n_ICONS_STARTMENU ${LANG_ENGLISH} \<br />    "In my &amp;Start Menu Programs folder"</pre>
<p>
We have to be careful with the encoding of these files, this English
one is not a problem, but the French one must be edited with the Windows
<code>CP-1252</code> charset for exemple.
These variables are simply used in our main script with, for example,
<code>$(l10n_SHORTCUTS_PAGE_TITLE)</code>.
</p>
<p>
Note that the ampersand <code>&amp;</code> in the string definitions
define an access key for controls in the UI, here there's <code>alt+D</code>
and <code>alt+S</code>.
</p>
</div>
<div class="howto-section">
<h4><span>3.4 Create the installer</span></h4>
<p>
We have now all the files to create the installer.
Let see our sources tree:
</p>
<pre>    |-samples_chapter_3<br />        |- data/<br />            |- icons/<br />                |- icon.ico<br />            |- myapp.bat<br />            |- myapp-res.rc<br />        |- myapp/<br />        |- win<br />            |- nsis/<br />                |- l10n/<br />                    |- en_US.nsh<br />                    |- fr.nsh<br />                |- myapp.nsi<br />            |- xal-src/<br />                |- build.sh<br />                |- clean.sh<br />                |- main.c</pre>
<p>
We have to build our launcher from the C source and our data (icon and resource).
And create 2 additional nsis scripts, listing our app files.
Then we can create the installer with <code>makensis</code>. We will doing
this in a temporary folder. Here's the script, named <code>build_win.sh</code>:
</p>
<pre>#!/bin/bash<br /><br /># exit the script on errors<br />set -e<br /><br />TMP_DIR=./tmp<br /><br /># get the absolute path of our TMP_DIR folder<br />TMP_DIR=$(readlink -f -- "$TMP_DIR")<br /><br /># re-create the TMP_DIR folder<br />rm -rfv "$TMP_DIR"<br />mkdir -v "$TMP_DIR"<br /><br /># copy our app<br />cp -rv myapp "$TMP_DIR/"<br /><br /># copy the XAL launcher sources<br />cp -rv win/xal-src "$TMP_DIR/xal"<br /># and our icon and resource file<br />cp -v data/icons/icon.ico "$TMP_DIR/xal/myapp.ico"<br />cp -v data/myapp-res.rc "$TMP_DIR/xal/"<br /><br /># build the launcher<br />cd "$TMP_DIR/xal/"<br />sh build.sh myapp myapp-res.rc<br />cd -<br /><br /># copy the launchers in the right folder<br />cp -v data/myapp.bat "$TMP_DIR/myapp/"<br />cp -v "$TMP_DIR/xal/myapp.exe" "$TMP_DIR/myapp/"<br /><br /># delete the xal sources<br />rm -rv "$TMP_DIR/xal"<br /><br /># create the nsis script listing the files to unsinstall<br />cd "$TMP_DIR/myapp"<br />find . -maxdepth 1 -type f &gt; ../uninstall_files.nsi<br />sed -i -r "s|^\./(.*)$|  Delete \"\$INSTDIR\\\\\1\"|" ../uninstall_files.nsi<br /><br /># and the list of directory<br />ls -d */ &gt; ../uninstall_dirs.nsi<br />sed -i -r "s|^(.*)/$|  RMDir /r \"\$INSTDIR\\\\\1\"|" ../uninstall_dirs.nsi<br />cd -<br /><br /># copy the other nsis scripts<br />cp -rv win/nsis/* "$TMP_DIR/"<br /><br /># and create the installer<br />makensis "$TMP_DIR/myapp.nsi"<br /><br /># finally, copy our installer in the root sources dir<br />cp -v "$TMP_DIR/MyApp-1.0-install.exe" ./<br /><br />echo "Windows installer for myapp created."</pre>
<p>To launch this script, in a terminal:</p>
<ul class="code-xterm">
<li><pre>cd samples_chapter_3</pre></li>
<li><pre>sh ./build_win.sh</pre></li>
</ul>
<p>
And as result we have finally the file <code>MyApp-1.0-install.exe</code>
in the <code>samples_chapter_3</code> folder :) .
</p>
</div>
<div class="howto-navigator-bottom">
<div class="howto-previous"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribute-your-XULRunner-app-24-Package-as-rpm" title="Go to chapter 2.4">&lt; previous chapter</a></div>
<div class="howto-next"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/26/Distribute-your-XULRunner-app-4-Mac-OSX" title="Go to chapter 4">next chapter &gt;</a></div>
<div class="clearer">&nbsp;</div>
</div>
<div class="howto-author">
<p>Nicolas Martin</p>
</div>
<div class="howto-download-section">
<p>
You can download all the samples of this chapter 3 (Windows) in the
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/dl.php?id=current_sample_3" class="howto-download-archive">samples_chapter_3.tar.gz</a>
archive.
</p>
</div>
<div class="howto-credits">
<p><em>
The myapp application, from
<a href="https://developer.mozilla.org/en/getting_started_with_xulrunner" rel="external">developer.mozilla.org</a>
is in the <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a>.
</em></p>
<p><em>
The icon used is from the
<a href="http://tango.freedesktop.org" rel="external">Tango Desktop Project</a>,
and is in the <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a>.
</em></p>
<p><em>
The C launcher
<a href="http://joliclic.free.fr/mozilla/xal/en/" rel="external">XUL App Launcher</a> (XAL)
is under the <a href="http://www.opensource.org/licenses/mit-license.php" rel="external">MIT license</a>.
</em></p>
<p><em>
All other added data, and sample files, of this chapter 3, are in the
<a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a> too.
</em></p>
</div>
<div class="howto-footer">
<p>
The content of this article
is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>
</p>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width: 0;" src="http://i.creativecommons.org/l/by-sa/3.0/80x15.png" /></a>
</div>
</div>]]></content:encoded>
</item>
     <item rdf:about="http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribuer-votre-appli-XULRunner-24-Empaqueter-un-rpm">
    <title>Distribuer votre appli XULRunner - 2.4 - Empaqueter un rpm</title>
    <link>http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribuer-votre-appli-XULRunner-24-Empaqueter-un-rpm</link>
    <dc:date>2011-05-24T13:32:00+00:00</dc:date>
    <dc:language>fr</dc:language>
    <dc:creator>Joliclic blog - mozilla</dc:creator>
    <dc:subject></dc:subject>
	<description></description>
	<content:encoded><![CDATA[    <div class="howto">
<p><em>This post exists also in <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribute-your-XULRunner-app-24-Package-as-rpm">english</a></em></p>
<p><em>
Ce billet fait partie d'une <a href="http://joliclic.free.fr/blog/index.php?tag/dist_xul_app_fr">série</a> sur comment déployer une application XULRunner.
Voir le <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/20/Distribuer-votre-appli-XULRunner-1-Preambule">préambule</a> pour le contexte.
</em></p>
<h3><span>2 - Linux</span></h3>
<h4><span>2.4 Empaqueter un rpm</span></h4>
<ul>
<li>2.4.1 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/#howtofr_dxr_2.4.1">Préalable</a></li>
<li>2.4.2 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/#howtofr_dxr_2.4.2">Fichiers RPM</a></li>
<li>2.4.3 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/#howtofr_dxr_2.4.3">Créer le rpm</a></li>
</ul>
<div class="howto-section">
<h5><span>2.4.1 Préalable</span></h5>
<p>
Dans cette partie nous  allons créer un paquet rpm, pour les
distributions basée sur rpm, comme Red Hat, Fedora, Suse,... (j'ai testé
uniquement sur Fedora, merci de me faire savoir si vous rencontrez des
problèmes sur les autres).
</p>
<p>
Nous pouvons créer ce rpm aussi bien depuis d'autres distributions Linux,
basées sur Debian par exemple (c'est ce que je fais), nous avons juste
besoin de l'executable <code>rpmbuild</code>, et pour celà il suffit
d'installer <code>rpm</code>&nbsp;:
</p>
<p><code class="code-xterm-root">apt-get install rpm</code></p>
<p>Quelques liens de documentation&nbsp;:</p>
<ul>
<li>
<a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/index.html" rel="external">The RPM Guide</a>
de Fedora
</li>
<li>
<a href="http://fedoraproject.org/wiki/Packaging/Guidelines" rel="external">The Packaging:Guidelines</a>
dans le wiki Fedora.
</li>
<li>
et le guide <a href="http://www.rpm.org/max-rpm/" rel="external">the Maximum RPM</a> de rpm.org
</li>
<li>
<a href="http://www.gurulabs.com/downloads/GURULABS-RPM-LAB/GURULABS-RPM-GUIDE-v1.0.PDF" rel="external">Cette documentation pdf</a>
de www.gurulabs.com est utile pour comprendre la création de rpm.
</li>
</ul>
<p>
Je suppose que nous n'avons pas besoin de compilation pour notre appli,
mais si ce n'est pas le cas, compiler simplement avant l'empaquètement
(malgré le fait que ce soit
<a href="http://fedoraproject.org/wiki/Packaging/Guidelines#No_inclusion_of_pre-built_binaries_or_libraries" rel="external">déconseillé</a>
dans ce guide).
</p>
</div>
<div class="howto-section">
<h5><span>2.4.2 Fichiers RPM</span></h5>
<p>
pour créer un rpm, nous sommes supposé paramétrer une configuration
utilisateur pour la création de tout rpm. Mais il est possible de faire
celà dans un dossier local, c'est ce que nous allons faire.
</p>
<p>
Nous devons créer les dossiers suivants, et un fichier
<code><strong>myapp.spec</strong></code>&nbsp;:
</p>
<pre>    |- samples_chapter_2/<br />        |- myapp/<br />        |- rpmbuild/<br />            |- BUILD/<br />            |- RPMS/<br />            |- SOURCES/<br />            |- SPECS/<br />            |- SRPMS/<br />            |- myapp.spec</pre>
<p>
En fait c'est la même structure que pour un environnement général de
création rpm, mais local.</p>
<p>
Le fichier <code><strong>.spec</strong></code> est le 'script' utilisé par
rpmbuild pour créer le rpm. Il est supposé utiliser une archive source au
format tar.gz, que nous allons créer spécialement pour lui plus tard.
</p>
<p>Voici le contenu de notre spec&nbsp;:</p>
<pre>Name:           myapp<br />Version:        1.0<br />Release:        1%{?dist}<br />Summary:        simple Hello World powered by XULRunner.<br /><br />Group:          Development/Tools<br />License:        MPLv1.1 or GPLv2+ or LGPLv2+<br />URL:            http://example.com/myapp/<br />Source:         myapp-1.0.tar.gz<br />BuildArch:      noarch<br />BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id} -un)<br /><br />#BuildRequires:  <br />Requires:       firefox &gt;= 3.6<br /><br />%description<br />simple Hello World<br />Powered by XULRunner.<br /><br />%prep<br />%setup<br /><br />%build<br /><br />%install<br />rm -rf %{buildroot}<br />mkdir -p %{buildroot}%{_libdir}<br />cp -R myapp %{buildroot}%{_libdir}/<br />mkdir -p %{buildroot}%{_bindir}<br /><br />ln -s %{_libdir}/myapp/myapp.sh %{buildroot}%{_bindir}/myapp<br /><br />mkdir -p %{buildroot}%{_datadir}/applications<br />cp data/myapp.desktop %{buildroot}%{_datadir}/applications/<br /><br />mkdir -p %{buildroot}%{_datadir}/icons/hicolor/16x16/apps<br />cp data/icons/icon16.png \<br />    %{buildroot}%{_datadir}/icons/hicolor/16x16/apps/myapp.png<br /><br />mkdir -p %{buildroot}%{_datadir}/icons/hicolor/22x22/apps<br />cp data/icons/icon22.png \<br />    %{buildroot}%{_datadir}/icons/hicolor/22x22/apps/myapp.png<br /><br />mkdir -p %{buildroot}%{_datadir}/icons/hicolor/32x32/apps<br />cp data/icons/icon32.png \<br />    %{buildroot}%{_datadir}/icons/hicolor/32x32/apps/myapp.png<br /><br />mkdir -p %{buildroot}%{_datadir}/icons/hicolor/48x48/apps<br />cp data/icons/icon48.png \<br />    %{buildroot}%{_datadir}/icons/hicolor/48x48/apps/myapp.png<br /><br />mkdir -p %{buildroot}%{_datadir}/icons/hicolor/scalable/apps<br />cp data/icons/icon48.svg \<br />    %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/myapp.svg<br /><br />%post<br />touch --no-create %{_datadir}/icons/hicolor &amp;&gt;/dev/null || :<br />if [ -x %{_bindir}/gtk-update-icon-cache ]; then<br />  %{_bindir}/gtk-update-icon-cache -q %{_datadir}/icons/hicolor;<br />fi<br /><br />%postun<br />touch --no-create %{_datadir}/icons/hicolor &amp;&gt;/dev/null || :<br />if [ -x %{_bindir}/gtk-update-icon-cache ]; then<br />  %{_bindir}/gtk-update-icon-cache -q %{_datadir}/icons/hicolor;<br />fi<br /><br /><br />%clean<br />rm -rf $RPM_BUILD_ROOT<br /><br /><br />%files<br />%defattr(-,root,root,-)<br />%{_bindir}/myapp<br />%{_libdir}/myapp<br />%{_datadir}/applications/myapp.desktop<br />%{_datadir}/icons/hicolor/16x16/apps/myapp.png<br />%{_datadir}/icons/hicolor/22x22/apps/myapp.png<br />%{_datadir}/icons/hicolor/32x32/apps/myapp.png<br />%{_datadir}/icons/hicolor/48x48/apps/myapp.png<br />%{_datadir}/icons/hicolor/scalable/apps/myapp.svg<br />#%doc<br /><br />%changelog<br />* Fri Oct  8 2010 John Doe &lt;johndoe@example.com&gt; 1.0-1<br />- first publication</pre>
<p>Voyons en détail certaines entrées de ce fichier&nbsp;:</p>
<p>
<code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s03.html#id1935997" rel="external">Name</a></strong></code>
ne devrait contenir aucun caractère blanc.
</p>
<p>
<code><strong>Version</strong></code> doit contenir uniquement des
chiffres (et des points), pas de chaîne comme "beta".
</p>
<p>
L'entrée <code><strong>Group</strong></code> doit être choisie dans la
liste du fichier <code>/usr/share/doc/rpm/GROUPS</code> . Vous devez
l'avoir sur votre ordinateur avec l'installation de rpm.
</p>
<p>
<code><strong>Release</strong></code> est la version du rpm pour cette
version de l'appli, et <code>%{?dist}</code>  sera remplacé par rpmbuild
par la distribution courante. Celà ne sera pas complété sur une distribution
non rpm (comme Debian), vous pouvez le supprimer si vous le désirez.
</p>
<p>
Pour l'entrée <code><strong>License</strong></code>, vous devez choisir
un mot clé court (short keyword)
<a href="http://fedoraproject.org/wiki/Licensing" rel="external">dans cette liste</a>.
</p>
<p>
L'entrée <code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s03s03.html" rel="external">Source</a></strong></code>
doit correspondre exactement au tar.gz que nous créerons plus tard.
</p>
<p>
La ligne <code><strong>BuildArch</strong>: noarch</code> spécifie que
notre appli n'est pas spécifique à l'architecture. Si votre appli
contient du code compilé, vous devez supprimer cette ligne, et un rpm
spécifique à l'architecture courante sera construit.
</p>
<p>
La valeur de <code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s03s02.html" rel="external">BuildRoot</a></strong></code>
est une valeur habituelle.
</p>
<p>
<code><strong>BuildRequires</strong></code> est commenté (avec un
<code>#</code>), comme nous n'avons pas de compilation.
</p>
<p>
Enfin, l'entrée
<code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-advanced-packaging.html#id1953487" rel="external">Requires</a></strong></code>
contient les autres paquets qui sont nécessaires au fonctionnement de notre appli.
Vous pourriez en ajouter d'autres, séparés par des virgules (<code>,</code>).
Notez que vous ne pouvez pas déclarer de dépendances alternatives, comme pour un deb.
C'est pourquoi nous déclarons Firefox et non XULRunner comme dépendance, dans le cas
éventuel où le Firefox de la distribution n'est pas basée sur XULRunner.
</p>
<p>
Par la suite nous copierons notre archive tar.gz dans le dossier SOURCES.
<br />
Puis la section
<code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch08s02s03s02.html" rel="external">%prep</a></strong></code>
et l'instruction <code>%setup</code>
la décompresseront dans le dossier BUILD.
<br />
La section <code><strong><a href="https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s04s02.html" rel="external">%build</a></strong></code>
est vide, parce que nous n'avons pas de compilation à faire.
</p>
<p>
Dans la section <code><strong>%install</strong></code>, nous installons notre appli.
<br />
Ce sont des commandes shell, le dossier courant de travail est la source tar.gz non compressée.
<code>%{buildroot}</code>  est la racine de l'installation local de notre appli,
ce sera la racine de l'ordinateur <code>/</code> lors de l'installation réelle.
<br />
<code>%{_libdir}</code>, <code>%{_bindir}</code>, et <code>%{_datadir}</code>
correspondent respectivement à <code>/usr/lib/</code>, <code>/usr/bin/</code>,
et <code>/usr/share/</code>. Je suppose que c'est le cas pour les principales
distributions basées sur rpm, si je me trompe, merci de me corriger, car il
faudrait alors redéfinir certaines variables.
<br />
Donc dans cette section, nous recréons le dossier initial buildroot.
Puis nous créons le lien vers notre lanceur dans <code>/usr/bin/</code>,
copions notre appli dans <code>/usr/lib/</code>, et copions notre fichier
desktop et nos icônes aux bons emplacements dans <code>/usr/share/</code>.
</p>
<p>
les sections <code><strong>%post</strong></code> et <code><strong>%postun</strong></code>
déclarent quelques actions après que notre appli sera installée ou désinstallée.
Nous mettons à jour la base des icônes pour le gestionnaire de fenêtre.
<br />
Si l'appli prend en charge certains types mime, i.e. peut ouvrir certains
type de fichier, celà doit être spécifier dans le fichier .desktop .
Et vous <strong>devez</strong> ajouter le code suivant dans ces sections
<code>%post</code> et <code>%postun</code>&nbsp;:
</p>
<pre>if [ -x /usr/bin/update-desktop-database ]; then<br />    update-desktop-database &amp;&gt; /dev/null || :<br />fi</pre>
<p>
La section <code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s05.html" rel="external">%files</a></strong></code>
est obligatoire, et contient la liste complète des fichiers/dossiers
installés par notre appli.
</p>
<p>
Enfin, le format de la section <code><strong>%changelog</strong></code>,
est décrite
<a href="http://fedoraproject.org/wiki/Packaging/Guidelines#Changelogs" rel="external">dans cette doc.</a>
</p>
</div>
<div class="howto-section">
<h5><span>2.4.3 Créer le rpm</span></h5>
<p>
Maintenant que nous avons tout ce dont nous avons besoin, nous allons
créer un script pour créer une "fausse" archive source pour rpmbuild,
qui contiendra notre appli, notre fichier desktop, et nos icônes.
Nous placerons cette archive dans le dossiers SOURCES, puis invoquerons
rpmbuild localement avec notre fichier spec. Et en fait, nous ferons tout
celà dans un dossier temporaire, pour laisser nos sources propres.
</p>
<p><em>
Note: <code>rmpbuild</code> semble bugger si il y a des espaces dans le
chemin du dossier de travail, donc faites attention avec le nom des
(sous)dossiers où vous placez les sources.
<br />
Le script suivant s'arrêtera si c'est le cas.
</em></p>
<p>Voilà ce script&nbsp;:</p>
<pre>#!/bin/bash<br /><br /># exit the script on errors<br />set -e<br /><br />TMP_DIR=./tmp<br />SRC_VERSION=1.0<br /><br /># get the absolute path of our TMP_DIR folder<br />TMP_DIR=$(readlink -f -- "$TMP_DIR")<br /><br /># re-create the TMP_DIR folder<br />rm -rfv "$TMP_DIR"<br />mkdir -v "$TMP_DIR"<br /><br /># copy the rmpbuild tree folder<br />cp -rv rpmbuild/* "$TMP_DIR/"<br /><br /># create a source tar.gz archive for rpmbuild into SOURCES<br />mkdir -v "$TMP_DIR/myapp-$SRC_VERSION"<br />cp -rv myapp "$TMP_DIR/myapp-$SRC_VERSION/"<br />cp -rv data "$TMP_DIR/myapp-$SRC_VERSION/"<br />cd "$TMP_DIR"<br /># clean eventual tempory files<br />find . -type f -name *.*~ -exec rm {} \;<br />tar -zcvf  "$TMP_DIR/SOURCES/myapp-$SRC_VERSION.tar.gz" \<br />    "myapp-$SRC_VERSION"<br />cd -<br />rm -rv "$TMP_DIR/myapp-$SRC_VERSION"<br /><br /># rmpbuild seems to have a bug, it can't handle a _topdir with whitespace<br />if [ -n "$(echo "$TMP_DIR" | grep '[ ]')" ]; then<br />    echo "the path '$TMP_DIR' contains whitespace, rpmbuild will failed. script aborted!"<br />    exit 1<br />fi<br /><br /># build the rpm from our spec, specify our local build tree<br />rpmbuild --define="_topdir $TMP_DIR" -bb "$TMP_DIR/myapp.spec"<br /><br /># and finally copy our created rpm in to into the current folder<br />cp -v "$TMP_DIR/RPMS/noarch/myapp-$SRC_VERSION-1.noarch.rpm" ./</pre>
<p>Pour créer notre rpm, dans un terminal&nbsp;:</p>
<ul class="code-xterm">
<li><pre>cd samples_chapter_2</pre></li>
<li><pre>sh ./build_rpm.sh</pre></li>
</ul>
<p>
Et en résultat nous avons finalement le fichier <code>myapp-1.0-1.noarch.rpm</code>
dans le dossier myapp-src :) .
</p>
</div>
<div class="howto-navigator-bottom">
<div class="howto-previous"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/Distribuer-votre-appli-XULRunner-23-Un-cas-special-deb-pour-Maemo" title="Aller au chapitre 2.3">&lt; chapitre précédent</a></div>
<div class="howto-next"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribuer-votre-appli-XULRunner-3-Windows" title="Aller au chapitre 3">chapitre suivant &gt;</a></div>
<div class="clearer">&nbsp;</div>
</div>
<div class="howto-author">
<p>Nicolas Martin</p>
</div>
<div class="howto-download-section">
<p>
Vous pouvez télécharger tous les exemples de ce chapitre 2 (Linux) dans l'archive
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/dl.php?id=current_sample_2" class="howto-download-archive">
samples_chapter_2.tar.gz
</a>.
</p>
</div>
<div class="howto-credits">
<p><em>
L'application myapp, de
<a href="https://developer.mozilla.org/en/getting_started_with_xulrunner" rel="external">developer.mozilla.org</a>,
est dans le <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domaine Public</a>.
</em></p>
<p><em>
L'icône utilisée est issue du
<a href="http://tango.freedesktop.org" rel="external">Tango Desktop Project</a>,
et est dans le <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domaine Public</a>.
</em></p>
<p><em>
Toutes les autres données ajoutées, et les fichiers en exemple, sont dans le
<a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domain Public</a> également.
</em></p>
</div>
<div class="howto-footer">
<p>
Le contenu de cet article est sous les termes de la licence
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>
</p>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width: 0;" src="http://i.creativecommons.org/l/by-sa/3.0/80x15.png" /></a>
</div>
</div>]]></content:encoded>
</item>
     <item rdf:about="http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribute-your-XULRunner-app-24-Package-as-rpm">
    <title>Distribute your XULRunner app - 2.4 - Package as rpm</title>
    <link>http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribute-your-XULRunner-app-24-Package-as-rpm</link>
    <dc:date>2011-05-24T13:30:00+00:00</dc:date>
    <dc:language>fr</dc:language>
    <dc:creator>Joliclic blog - mozilla</dc:creator>
    <dc:subject></dc:subject>
	<description></description>
	<content:encoded><![CDATA[    <div class="howto">
<p><em>Ce billet existe aussi en <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribuer-votre-appli-XULRunner-24-Empaqueter-un-rpm">français</a></em></p>
<p><em>
This post is part of a <a href="http://joliclic.free.fr/blog/index.php?tag/dist_xul_app_en">series</a> about how to package a XULRunner application.<br />
See the <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/20/Distribute-your-XULRunner-app-1-Preamble">preamble</a> for the context case.
</em></p>
<h3><span>2.4 Package as rpm</span></h3>
<ul>
<li>2.4.1 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/#howto_dxr_2.4.1">Prerequisites</a></li>
<li>2.4.2 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/#howto_dxr_2.4.2">RPM files</a></li>
<li>2.4.3 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/#howto_dxr_2.4.3">Create the rpm</a></li>
</ul>
<div class="howto-section">
<h4><span>2.4.1 Prerequisites</span></h4>
<p>
In this part we will create a rpm package, for rpm based distributions,
like Red Hat, Fedora, Suse,... (I have tested only with Fedora, please
let me know if there's any problems for others).
</p>
<p>
We can create this rpm from other Linux distributions as well, Debian
based for example (that's what I do), we just need the
<code>rpmbuild</code> executable, we have just to install
<code>rpm</code>:
</p>
<p><code class="code-xterm-root">apt-get install rpm</code></p>
<p>Some documentation links:</p>
<ul>
<li>
<a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/index.html" rel="external">The RPM Guide</a>
from Fedora
</li>
<li>
<a href="http://fedoraproject.org/wiki/Packaging/Guidelines" rel="external">The Packaging:Guidelines</a>
in the Fedora wiki.
</li>
<li>
and <a href="http://www.rpm.org/max-rpm/" rel="external">the Maximum RPM</a>
guide from rpm.org
</li>
<li>
<a href="http://www.gurulabs.com/downloads/GURULABS-RPM-LAB/GURULABS-RPM-GUIDE-v1.0.PDF" rel="external">This pdf documentation</a>
from www.gurulabs.com is useful to understand the creation of rpm.
</li>
</ul>
<p>
I suppose we don't have any needed compilation, but if you have some,
simply do it before packaging (despite the fact this is
<a href="http://fedoraproject.org/wiki/Packaging/Guidelines#No_inclusion_of_pre-built_binaries_or_libraries" rel="external">not recommended</a>
in this guide).
</p>
</div>
<div class="howto-section">
<h4><span>2.4.2 RPM files</span></h4>
<p>
To build a rpm, we're supposed to setup a user configuration for all rpm
creation. But it is possible to do it in a local folder, that's what we
will do.
</p>
<p>
We need to create the following folders, and a
<code><strong>myapp.spec</strong></code> file:
</p>
<pre>    |- samples_chapter_2/<br />        |- myapp/<br />        |- rpmbuild/<br />            |- BUILD/<br />            |- RPMS/<br />            |- SOURCES/<br />            |- SPECS/<br />            |- SRPMS/<br />            |- myapp.spec</pre>
<p>
In fact this is the same structure than the required rpm environnement,
but locally.
</p>
<p>
The <code><strong>.spec</strong></code> file is the 'script' used by
rpmbuild to create the rpm. It is supposed to use a source tar.gz
archive, that we will build especially later.
</p>
<p>Here's the content of our spec:</p>
<pre>Name:           myapp<br />Version:        1.0<br />Release:        1%{?dist}<br />Summary:        simple Hello World powered by XULRunner.<br /><br />Group:          Development/Tools<br />License:        MPLv1.1 or GPLv2+ or LGPLv2+<br />URL:            http://example.com/myapp/<br />Source:         myapp-1.0.tar.gz<br />BuildArch:      noarch<br />BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id} -un)<br /><br />#BuildRequires:  <br />Requires:       firefox &gt;= 3.6<br /><br />%description<br />simple Hello World<br />Powered by XULRunner.<br /><br />%prep<br />%setup<br /><br />%build<br /><br />%install<br />rm -rf %{buildroot}<br />mkdir -p %{buildroot}%{_libdir}<br />cp -R myapp %{buildroot}%{_libdir}/<br />mkdir -p %{buildroot}%{_bindir}<br /><br />ln -s %{_libdir}/myapp/myapp.sh %{buildroot}%{_bindir}/myapp<br /><br />mkdir -p %{buildroot}%{_datadir}/applications<br />cp data/myapp.desktop %{buildroot}%{_datadir}/applications/<br /><br />mkdir -p %{buildroot}%{_datadir}/icons/hicolor/16x16/apps<br />cp data/icons/icon16.png \<br />    %{buildroot}%{_datadir}/icons/hicolor/16x16/apps/myapp.png<br /><br />mkdir -p %{buildroot}%{_datadir}/icons/hicolor/22x22/apps<br />cp data/icons/icon22.png \<br />    %{buildroot}%{_datadir}/icons/hicolor/22x22/apps/myapp.png<br /><br />mkdir -p %{buildroot}%{_datadir}/icons/hicolor/32x32/apps<br />cp data/icons/icon32.png \<br />    %{buildroot}%{_datadir}/icons/hicolor/32x32/apps/myapp.png<br /><br />mkdir -p %{buildroot}%{_datadir}/icons/hicolor/48x48/apps<br />cp data/icons/icon48.png \<br />    %{buildroot}%{_datadir}/icons/hicolor/48x48/apps/myapp.png<br /><br />mkdir -p %{buildroot}%{_datadir}/icons/hicolor/scalable/apps<br />cp data/icons/icon48.svg \<br />    %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/myapp.svg<br /><br />%post<br />touch --no-create %{_datadir}/icons/hicolor &amp;&gt;/dev/null || :<br />if [ -x %{_bindir}/gtk-update-icon-cache ]; then<br />  %{_bindir}/gtk-update-icon-cache -q %{_datadir}/icons/hicolor;<br />fi<br /><br />%postun<br />touch --no-create %{_datadir}/icons/hicolor &amp;&gt;/dev/null || :<br />if [ -x %{_bindir}/gtk-update-icon-cache ]; then<br />  %{_bindir}/gtk-update-icon-cache -q %{_datadir}/icons/hicolor;<br />fi<br /><br /><br />%clean<br />rm -rf $RPM_BUILD_ROOT<br /><br /><br />%files<br />%defattr(-,root,root,-)<br />%{_bindir}/myapp<br />%{_libdir}/myapp<br />%{_datadir}/applications/myapp.desktop<br />%{_datadir}/icons/hicolor/16x16/apps/myapp.png<br />%{_datadir}/icons/hicolor/22x22/apps/myapp.png<br />%{_datadir}/icons/hicolor/32x32/apps/myapp.png<br />%{_datadir}/icons/hicolor/48x48/apps/myapp.png<br />%{_datadir}/icons/hicolor/scalable/apps/myapp.svg<br />#%doc<br /><br />%changelog<br />* Fri Oct  8 2010 John Doe &lt;johndoe@example.com&gt; 1.0-1<br />- first publication</pre>
<p>Let see in detail some entries of this file:</p>
<p>
The <code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s03.html#id1935997" rel="external">Name</a></strong></code>
should not contain any whitespace characters.
</p>
<p>
The <code><strong>Version</strong></code> must contain only number and
digit, no string like "beta".
</p>
<p>
The <code><strong>Group</strong></code> entry must be chosen in the
list in the <code>/usr/share/doc/rpm/GROUPS</code> file. You should have
it on your computer since you have installed rpm.
</p>
<p>
The <code><strong>Release</strong> </code>is the version of the rpm for
this version of the app, and <code>%{?dist}</code> will be replaced by
rpmbuild by the current distribution. It will not be completed on a non
rpm distribution, you can remove it if you want.
</p>
<p>
For the <code><strong>License</strong></code> entry, you must choose a short keyword
<a href="http://fedoraproject.org/wiki/Licensing" rel="external">from this list</a>.
</p>
<p>
The <code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s03s03.html" rel="external">Source</a></strong></code>
entry must match exactly the tar.gz that we will create later.
</p>
<p>
The <code><strong>BuildArch</strong>: noarch</code> line specify that our
app is not architecture specific. If your app contains some compiled code,
you must remove this line, and a rpm specific to the current architecture
will be build.
</p>
<p>
The <code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s03s02.html" rel="external">BuildRoot</a></strong></code>
value is a usual one.
</p>
<p>
The <code><strong>BuildRequires</strong></code> is commented (with a
<code>#</code>), as we have no compilations.
</p>
<p>
Finally, the
<code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-advanced-packaging.html#id1953487" rel="external">Requires</a></strong></code>
entry contains the other packages that are needed by our
app. You could add others, separated by comma (<code>,</code>). Note that you
can't declare alternative dependencies like with deb. That's why we declare
Firefox and not XULRunner as dependencies, in the eventual case where the Firefox
of the distribution is not XULRunner based.
</p>
<p>
Later we will copy the tar.gz archive of our app into the SOURCES folder.
<br />
Then the
<code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch08s02s03s02.html" rel="external">%prep</a></strong></code>
section and the <code>%setup</code> instruction
will unpack it into the BUILD folder.
<br />
The <code><strong><a href="https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s04s02.html" rel="external">%build</a></strong></code>
section is empty, because we have no compilation
to do.
</p>
<p>
In the <code><strong>%install</strong></code> section, we install our app.
<br />
These  are some shell commands, the current working directory is the unpacked
source tar.gz. <code>%{buildroot}</code> is the root of the local
installation of our app,  this will be the computer root <code>/</code> in
the real installation.
<br />
<code>%{_libdir}</code>, <code>%{_bindir}</code>, and <code>%{_datadir}</code>
corresponds respectively to <code>/usr/lib/</code>, <code>/usr/bin/</code>,
and <code>/usr/share/</code>. I guess that's the case for main rpm based distros,
If I'm wrong, please correct me, it means that some these variables
should be redefined.
<br />
So in this section, we re-create the initial buildroot folder.
Then we create the link to our launcher in <code>/usr/bin/</code>,
copy our app in <code>/usr/lib/</code>, and copy the desktop file and our icons
into the right location in <code>/usr/share/</code>.
</p>
<p>
The <code><strong>%post</strong></code> and <code><strong>%postun</strong></code>
sections declare some actions after that our app will be installed and uninstalled.
We update the icons database for the windows manager.
<br />
If the app handle some mime types, i.e. can open some type of files, this should be
specified in the .desktop file.
And you <strong>must</strong> add the following code in these
<code>%post</code> and <code>%postun</code> sections:
</p>
<pre>if [ -x /usr/bin/update-desktop-database ]; then<br />    update-desktop-database &amp;&gt; /dev/null || :<br />fi</pre>
<p>
The <code><strong><a href="http://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch09s05.html" rel="external">%files</a></strong></code>
section is required, and contains the
complete list of files/folders installed by our app.
</p>
<p>
Finally, the format of the <code><strong>%changelog</strong></code> section,
is described <a href="http://fedoraproject.org/wiki/Packaging/Guidelines#Changelogs" rel="external">in this doc.</a>
</p>
</div>
<div class="howto-section">
<h4><span>2.4.3 Create the rpm</span></h4>
<p>
So now that we have all that we need, we will create a script to create
a fake source archive for rpmbuild, which contains our app, our desktop file,
and our icons. We will place this archive in the SOURCES folder, then invoke
rpmbuild locally with our spec file. And in fact, we will doing all of this
in a temporary folder, to let our sources clean.
</p>
<p><em>
Note: <code>rmpbuild</code> seems to bug if there's some whitespace in
the path of the working folder, so be careful with the name of the
(sub)directories where you place your sources.
<br />
The following script will abort if this is the case.
</em></p>
<p>Here this script:</p>
<pre>#!/bin/bash<br /><br /># exit the script on errors<br />set -e<br /><br />TMP_DIR=./tmp<br />SRC_VERSION=1.0<br /><br /># get the absolute path of our TMP_DIR folder<br />TMP_DIR=$(readlink -f -- "$TMP_DIR")<br /><br /># re-create the TMP_DIR folder<br />rm -rfv "$TMP_DIR"<br />mkdir -v "$TMP_DIR"<br /><br /># copy the rmpbuild tree folder<br />cp -rv rpmbuild/* "$TMP_DIR/"<br /><br /># create a source tar.gz archive for rpmbuild into SOURCES<br />mkdir -v "$TMP_DIR/myapp-$SRC_VERSION"<br />cp -rv myapp "$TMP_DIR/myapp-$SRC_VERSION/"<br />cp -rv data "$TMP_DIR/myapp-$SRC_VERSION/"<br />cd "$TMP_DIR"<br /># clean eventual tempory files<br />find . -type f -name *.*~ -exec rm {} \;<br />tar -zcvf  "$TMP_DIR/SOURCES/myapp-$SRC_VERSION.tar.gz" \<br />    "myapp-$SRC_VERSION"<br />cd -<br />rm -rv "$TMP_DIR/myapp-$SRC_VERSION"<br /><br /># rmpbuild seems to have a bug, it can't handle a _topdir with whitespace<br />if [ -n "$(echo "$TMP_DIR" | grep '[ ]')" ]; then<br />    echo "the path '$TMP_DIR' contains whitespace, rpmbuild will failed. script aborted!"<br />    exit 1<br />fi<br /><br /># build the rpm from our spec, specify our local build tree<br />rpmbuild --define="_topdir $TMP_DIR" -bb "$TMP_DIR/myapp.spec"<br /><br /># and finally copy our created rpm in to into the current folder<br />cp -v "$TMP_DIR/RPMS/noarch/myapp-$SRC_VERSION-1.noarch.rpm" ./</pre>
<p>To create our rpm, in a terminal:</p>
<ul class="code-xterm">
<li><pre>cd samples_chapter_2</pre></li>
<li><pre>sh ./build_rpm.sh</pre></li>
</ul>
<p>
And as result we have finally the file <code>myapp-1.0-1.noarch.rpm</code>
in the myapp-src folder :) .
</p>
</div>
<div class="howto-navigator-bottom">
<div class="howto-previous"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/Distribute-your-XULRunner-app-23-Special-case-deb-for-Maemo" title="Go to chapter 2.3">&lt; previous chapter</a></div>
<div class="howto-next"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/25/Distribute-your-XULRunner-app-3-Windows" title="Go to chapter 3">next chapter &gt;</a></div>
<div class="clearer">&nbsp;</div>
</div>
<div class="howto-author">
<p>Nicolas Martin</p>
</div>
<div class="howto-download-section">
<p>
You can download all the samples of this chapter 2 (Linux) in the
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/dl.php?id=current_sample_2" class="howto-download-archive">samples_chapter_2.tar.gz</a>
archive.
</p>
</div>
<div class="howto-credits">
<p><em>
The myapp application, from
<a href="https://developer.mozilla.org/en/getting_started_with_xulrunner" rel="external">developer.mozilla.org</a>
is in the <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a>.
</em></p>
<p><em>
The icon used is from the
<a href="http://tango.freedesktop.org" rel="external">Tango Desktop Project</a>,
and is in the <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a>.
</em></p>
<p><em>
All added data, and sample files, of this chapter 2, are in the
<a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a> too.
</em></p>
</div>
<div class="howto-footer">
<p>
The content of this article
is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>
</p>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width: 0;" src="http://i.creativecommons.org/l/by-sa/3.0/80x15.png" /></a>
</div>
</div>]]></content:encoded>
</item>
     <item rdf:about="http://joliclic.free.fr/blog/index.php?post/2011/05/23/Distribuer-votre-appli-XULRunner-23-Un-cas-special-deb-pour-Maemo">
    <title>Distribuer votre appli XULRunner - 2.3 Un cas spécial, deb pour Maemo</title>
    <link>http://joliclic.free.fr/blog/index.php?post/2011/05/23/Distribuer-votre-appli-XULRunner-23-Un-cas-special-deb-pour-Maemo</link>
    <dc:date>2011-05-23T10:49:00+00:00</dc:date>
    <dc:language>fr</dc:language>
    <dc:creator>Joliclic blog - mozilla</dc:creator>
    <dc:subject></dc:subject>
	<description></description>
	<content:encoded><![CDATA[    <div class="howto">
<p><em>This post exists also in <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/Distribute-your-XULRunner-app-23-Special-case-deb-for-Maemo">english</a></em></p>
<p><em>
Ce billet fait partie d'une <a href="http://joliclic.free.fr/blog/index.php?tag/dist_xul_app_fr">série</a> sur comment déployer une application XULRunner.
Voir le <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/20/Distribuer-votre-appli-XULRunner-1-Preambule">préambule</a> pour le contexte.
</em></p>
<h3><span>2 - Linux</span></h3>
<h4><span>2.3 Un cas spécial : deb pour Maemo</span></h4>
<ul>
<li>2.3.1 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howtofr_dxr_2.3.1">Maemo - généralités</a></li>
<li>2.3.2 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howtofr_dxr_2.3.2">Adapter le lanceur</a></li>
<li>2.3.3 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howtofr_dxr_2.3.3">Nouvelle organisation des fichiers - Où placer notre appli</a></li>
<li>2.3.4 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howtofr_dxr_2.3.4">Additions au fichier <code>.desktop</code></a></li>
<li>2.3.5 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howtofr_dxr_2.3.5">Changements aux fichiers Debian</a></li>
<li>2.3.6 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howtofr_dxr_2.3.6">Créer le deb</a></li>
</ul>
<div class="howto-section">
<h5><span>2.3.1 Maemo - généralités</span></h5>
<p>
Maemo est une distribution Linux basée sur Debian, pour les mobiles. Et
Firefox Mobile, nom de code Fennec, y est disponible.
<br />
<strong>Fennec</strong>, comme la version standard de Firefox, peut lancer
une appli XULRunner via l'argument <code>-app</code>.
</p>
<p>
Donc, a priori, nous pouvons lancer toutes les applications XULRunner.
Bien sûr nous devrions tenir compte des spécificités des appareils
mobiles, petit écran (mais avec une haute résolution), et écran tactile.
Ce n'est pas le propos de ce tutoriel. Mais, telle quelle, notre appli
devrait fonctionner.
</p>
<p>
Cette plateforme étant basée sur Debian, nous distribuerons un deb pour
notre appli. Nous devons juste adapter quelques parties du
<a href="http://joliclic.free.fr/blog/index.php?post/2011/05/22/Distribuer-votre-appli-XULRunner-22-Empaqueter-un-deb">chapitre précédent</a> aux spécificités de Maemo.
</p>
<p>
Le <a href="http://wiki.maemo.org/Packaging/Guidelines" rel="external">Maemo Wiki</a>
contient quelques informations intéressantes.
</p>
</div>
<div class="howto-section">
<h5><span>2.3.2 Adapter le lanceur</span></h5>
<p>
Le changement est que nous invoquons Fennec à la place de Firefox.
<br />
Le nouveau lanceur, <code>myapp.sh</code>&nbsp;:
</p>
<pre>#!/bin/sh<br /><br />CUR_DIR=$(dirname $(readlink -f "$0"))<br /><br />if [ -x /usr/bin/fennec ]; then<br />    /usr/bin/fennec -app "$CUR_DIR/application.ini" $@<br />elif [ -x /usr/bin/xulrunner ]; then<br />    /usr/bin/xulrunner "$CUR_DIR/application.ini" $@<br />else<br />    echo "Error: unable to find Fennec or XULRunner!"<br />fi</pre>
</div>
<div class="howto-section">
<h5><span>2.3.3 Nouvelle organisation des fichiers - Où placer notre appli</span></h5>
<p>
Sur Maemo, à cause de l'espace mémoire des appareils mobiles, les applications
doivent résider dans le dossier <code>/opt/</code> plutôt que dans
<code>/usr/lib/</code> ou <code>/usr/share/</code>.
</p>
<p>
Donc nous allons copier notre <strong>appli dans <code>/opt/myapp/</code></strong>.
<br />
Un sous dossier serait possible également,
<code>/opt/myorganization/myapp/</code> par exemple.
</p>
<p>
Pour les icônes, nous utiliserons des dimensions différentes que pour le
bureau, comme le fait Fennec&nbsp;:
1 png de 26x26px png, 1 png de 40x40px, et 1 svg de  48x48px.
<br />
Leurs destinations finales changent un peu également, elles doivent
être placées dans&nbsp;:
</p>
<ul>
<li>/usr/share/icons/hicolor/26x26/hildon/myapp.png</li>
<li>/usr/share/icons/hicolor/40x40/hildon/myapp.png</li>
<li>/usr/share/icons/hicolor/scalable/hildon/myapp.svg</li>
</ul>
<p>
L'emplacement du fichier <code>.desktop</code> change aussi, il doit être
placé dans <code>/usr/share/applications/hildon/</code> .
</p>
<p>
Le fichier <code>.desktop</code> et les images ne sont pas trop lourdes,
nous pouvons les placer ainsi, mais il serait possible de les placer dans
notre dossier principal d'application et d'utiliser des liens symboliques.
</p>
</div>
<div class="howto-section">
<h5><span>2.3.4 Additions au fichier <code>.desktop</code></span></h5>
<p>
Quelques informations peuvent être trouvées dans
<a href="http://wiki.maemo.org/Desktop_file_format" rel="external">cette page du Wiki Maemo</a>.
</p>
<p>
Quelques clés additionnelles peuvent être utilisées dans le fichier desktop.
Certaines que j'ajoute ne sont pas documentées, mais semblent être utilisées
par beaucoup de programmes, peut être pour d'anciennes version de Maemo.
<br />
Voici quelques lignes ajoutées à notre fichier desktop&nbsp;:
</p>
<pre>X-Icon-Path=/usr/share/icons<br />X-Window-Icon=myapp<br />X-Window-Icon-dimmed=myapp<br />X-Osso-Type=application/x-executable</pre>
</div>
<div class="howto-section">
<h5><span>2.3.5 Changements aux fichiers Debian</span></h5>
<p>
Pour éviter d'écraser le deb générique créé dans le chapitre précédent,
nous allons renommer ce nouveau paquet deb pour Maemo. Nous utiliserons
'myapp-mobile'. Pour être cohérent avec le processus debhelper, voici la
liste de tous ces changements&nbsp;:
</p>
<ul>
<li>
<p>
Dans le fichier <code>changelog</code>, la ligne
<code>myapp (1.0-1) unstable; urgency=low</code> devient
<code>myapp-mobile (1.0-1) unstable; urgency=low</code>
</p>
</li>
<li>
<p>
Dans le fichier <code>control</code>, la valeur pour les champs
<code>Source</code> et <code>Package</code> est changée en
<code>myapp-mobile</code>
</p>
</li>
<li>
<p>
Le ficher <code>myapp.links</code>  est renommé en <code>myapp-mobile.links</code>
</p>
</li>
</ul>
<p><strong>Autres changements au fichier <code>control</code>&nbsp;:</strong></p>
<p>
D'après
<a href="http://wiki.maemo.org/Packaging/Guidelines#Sections" rel="external">cette documentation</a>,
nous devons choisir une <code><strong>Section</strong></code> dans cette liste&nbsp;:
</p>
<ul>
<li><code>user/desktop</code></li>
<li><code>user/development</code></li>
<li><code>user/education</code></li>
<li><code>user/games</code></li>
<li><code>user/graphics</code></li>
<li><code>user/multimedia</code></li>
<li><code>user/navigation</code></li>
<li><code>user/network</code></li>
<li><code>user/office</code></li>
<li><code>user/science</code></li>
<li><code>user/system</code></li>
<li><code>user/utilities</code></li>
</ul>
<p>
Nous pouvons ajouter des données supplémentaires au fichier control,
utilisé pour construire le deb.
<br />
le premier est <code><strong>XB-Maemo-Display-Name</strong>: MyApp</code> .
</p>
<p>
Le deuxième est une icône base64, utilisée par le gestionnaire d'applications de Maemo,
<strong><code>XB-Maemo-Icon-26</code></strong>.
</p>
<p>
Nous utiliserons un script bash pour créer cette valeur base64 à partir d'une
icône png de 48px.
</p>
<p>Nous avons besoin du programme <code>uuencode</code>, sur debian/ubuntu&nbsp;:</p>
<p><code class="code-xterm-root">apt-get install sharutils</code></p>
<p>
puis nous créons un script bash nommé <code>build_base64.sh</code> pour convertir
un png de 48x48px en la valeur texte désirée&nbsp;:
</p>
<pre>#!/bin/bash<br /><br />set -e<br /><br /># base64 conversion<br />uuencode -m icon48.png icon48.png &gt; icon48.txt<br /><br /># remove the first line (begin-base64 ...)<br />sed -i '1d' icon48.txt<br /><br /># and the last line (====)<br />sed -i '$d' icon48.txt<br /><br /># add 4 spaces at the beginning of each lines<br />sed -i "s/^/    /" icon48.txt<br /><br /># and add a blank line at the end of the file<br />echo '' &gt;&gt; icon48.txt</pre>
<p>
vous pouvez trouvez ce script dans le dossier <code>data/icons</code>
de l'archive <code>samples_chapter_2.tar.gz</code>. Pour le lancer
(depuis le dossier icons)&nbsp;:
</p>
<p><kbd class="code-xterm">sh build_base64.sh</kbd></p>
<p>
Nous pouvons maintenant utilisé le contenu de icon48.txt comme valeur de
<code>XB-Maemo-Icon-26</code>  dans notre fichier control.
</p>
</div>
<div class="howto-section">
<h5><span>2.3.6 Créer le deb</span></h5>
<p>
Et c'est tout, nous pouvons maintenant créer notre deb comme dans le
chapitre précédent.
</p>
<p>
Je n'écris pas ici le script <code>build_maemodeb.sh</code>, c'est
pratiquement le même que celui pour construire le paquet générique
debian. Vous le trouverez dans l'archive jointe.
</p>
<ul class="code-xterm">
<li><pre>cd samples_chapter_2</pre></li>
<li><pre>sh ./build_maemodeb.sh</pre></li>
</ul>
<p><em>
Note: je suppose dans ce tutoriel que nous n'avons pas de code compilé
dans notre appli.
<br />
Si ce n'est pas le cas, nous <strong>devons</strong> utiliser
<strong><a href="http://wiki.maemo.org/Documentation/Maemo_5_Developer_Guide/Development_Environment/Maemo_SDK#Scratchbox" rel="external">scratchbox</a></strong>
pour compiler, et nous
<strong>devons utiliser scratchbox pour construire le deb</strong> aussi&nbsp;!
<br />
Et, comme dans le chapitre précédent, ne pas utiliser la ligne
<code>Architecture: all</code> dans le fichier control.
</em></p>
</div>
<div class="howto-navigator-bottom">
<div class="howto-previous"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/22/Distribuer-votre-appli-XULRunner-22-Empaqueter-un-deb" title="Aller au chapitre 2.2">&lt; chapitre précédent</a></div>
<div class="howto-next"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribuer-votre-appli-XULRunner-24-Empaqueter-un-rpm" title="Aller au chapitre 2.4">chapitre suivant &gt;</a></div>
<div class="clearer">&nbsp;</div>
</div>
<div class="howto-author">
<p>Nicolas Martin</p>
</div>
<div class="howto-download-section">
<p>
Vous pouvez télécharger tous les exemples de ce chapitre 2 (Linux) dans l'archive
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/dl.php?id=current_sample_2" class="howto-download-archive">
samples_chapter_2.tar.gz
</a>.
</p>
</div>
<div class="howto-credits">
<p><em>
L'application myapp, de
<a href="https://developer.mozilla.org/en/getting_started_with_xulrunner" rel="external">developer.mozilla.org</a>,
est dans le <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domaine Public</a>.
</em></p>
<p><em>
L'icône utilisée est issue du
<a href="http://tango.freedesktop.org" rel="external">Tango Desktop Project</a>,
et est dans le <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domaine Public</a>.
</em></p>
<p><em>
Toutes les autres données ajoutées, et les fichiers en exemple, sont dans le
<a href="http://wiki.creativecommons.org/Public_domain" rel="external">Domain Public</a> également.
</em></p>
</div>
<div class="howto-footer">
<p>
Le contenu de cet article est sous les termes de la licence
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>
</p>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width: 0;" src="http://i.creativecommons.org/l/by-sa/3.0/80x15.png" /></a>
</div>
</div>]]></content:encoded>
</item>
     <item rdf:about="http://joliclic.free.fr/blog/index.php?post/2011/05/23/Distribute-your-XULRunner-app-23-Special-case-deb-for-Maemo">
    <title>Distribute your XULRunner app - 2.3 - Special case, deb for Maemo</title>
    <link>http://joliclic.free.fr/blog/index.php?post/2011/05/23/Distribute-your-XULRunner-app-23-Special-case-deb-for-Maemo</link>
    <dc:date>2011-05-23T10:47:00+00:00</dc:date>
    <dc:language>fr</dc:language>
    <dc:creator>Joliclic blog - mozilla</dc:creator>
    <dc:subject></dc:subject>
	<description></description>
	<content:encoded><![CDATA[    <div class="howto">
<p><em>Ce billet existe aussi en <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/Distribuer-votre-appli-XULRunner-23-Un-cas-special-deb-pour-Maemo">français</a></em></p>
<p><em>
This post is part of a <a href="http://joliclic.free.fr/blog/index.php?tag/dist_xul_app_en">series</a> about how to package a XULRunner application.<br />
See the <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/20/Distribute-your-XULRunner-app-1-Preamble">preamble</a> for the context case.
</em></p>
<h3><span>2.3 Special case : deb for Maemo</span></h3>
<ul>
<li>2.3.1 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howto_dxr_2.3.1">Maemo generalities</a></li>
<li>2.3.2 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howto_dxr_2.3.2">Adapt the launcher</a></li>
<li>2.3.3 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howto_dxr_2.3.3">A new file system organization - Where place our app</a></li>
<li>2.3.4 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howto_dxr_2.3.4">Additions to the <code>.desktop</code> file</a></li>
<li>2.3.5 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howto_dxr_2.3.5">Changes to the Debian files</a></li>
<li>2.3.6 <a href="http://joliclic.free.fr/blog/index.php?post/2011/05/23/#howto_dxr_2.3.6">Create the deb</a></li>
</ul>
<div class="howto-section">
<h4><span>2.3.1 Maemo generalities</span></h4>
<p>
Maemo is a Linux, Debian based, distribution, for Mobile. And Firefox
Mobile, aka Fennec, is available on this platform.
<br />
<strong>Fennec</strong>, like the desktop version of Firefox, is able to
launch a XULRunner application via the <code>-app</code> argument.
</p>
<p>
So, a priori, we can launch any XULRunner applications. Of course, we
should care of the specificities of mobile devices, small screen (but
with high resolution), and touch screen. That's not the purpose of this
howto. But as is, our app should work.
</p>
<p>
Because this platform is Debian based, we will distribute our app with a
deb. We have just to adapt some parts of the
<a href="http://joliclic.free.fr/blog/index.php?post/2011/05/22/Distribute-your-XULRunner-app-22-Package-as-deb">previous chapter</a> to the specificities of
Maemo.
</p>
<p>
We can find <a href="http://wiki.maemo.org/Packaging/Guidelines" rel="external">some information in the Maemo Wiki</a>.
</p>
</div>
<div class="howto-section">
<h4><span>2.3.2 Adapt the launcher</span></h4>
<p>
The change is that we invoke Fennec rather than Firefox.
<br />
The new launcher, <code>myapp.sh</code>:
</p>
<pre>#!/bin/sh<br /><br />CUR_DIR=$(dirname $(readlink -f "$0"))<br /><br />if [ -x /usr/bin/fennec ]; then<br />    /usr/bin/fennec -app "$CUR_DIR/application.ini" $@<br />elif [ -x /usr/bin/xulrunner ]; then<br />    /usr/bin/xulrunner "$CUR_DIR/application.ini" $@<br />else<br />    echo "Error: unable to find Fennec or XULRunner!"<br />fi</pre>
</div>
<div class="howto-section">
<h4><span>2.3.3 A new file system organization - Where place our app</span></h4>
<p>
On Maemo, due to the memory space on mobile devices,
the applications should reside in the folder <code>/opt/</code> rather than
in <code>/usr/lib/</code> or <code>/usr/share/</code>.
</p>
<p>
So, we will copy our <strong>app in <code>/opt/myapp/</code></strong>.
<br />
A sub-directory would possible too,
<code>/opt/myorganization/myapp/</code> for example.
</p>
<p>
For the icons, we will use different dimensions than for the desktop,
like Fennec does itself:
a 26x26px png, a 40x40px png, and a 48x48 svg.
<br />
Their final locations change a little too, they must be placed in:
</p>
<ul>
<li>/usr/share/icons/hicolor/26x26/hildon/myapp.png</li>
<li>/usr/share/icons/hicolor/40x40/hildon/myapp.png</li>
<li>/usr/share/icons/hicolor/scalable/hildon/myapp.svg</li>
</ul>
<p>
The location of the <code>.desktop</code> file change too, it must be
placed into <code>/usr/share/applications/hildon/</code> .
</p>
<p>
The <code>.desktop</code> file and the images are not so heavy, we can
put them as is, but it should be possible to place them in our main app
folder and use symbolic links too.
</p>
</div>
<div class="howto-section">
<h4><span>2.3.4 Additions to the <code>.desktop</code> file</span></h4>
<p>
Some information can be found in
<a href="http://wiki.maemo.org/Desktop_file_format" rel="external">this page of the Maemo Wiki</a>.
</p>
<p>
Some additional keys can be used in the desktop file. Not all that I add
are documentated, but they seems to be used by a lot of programs,
perhaps for some older version of Maemo.
<br />
Here's some lines added to our desktop file:
</p>
<pre>X-Icon-Path=/usr/share/icons<br />X-Window-Icon=myapp<br />X-Window-Icon-dimmed=myapp<br />X-Osso-Type=application/x-executable</pre>
</div>
<div class="howto-section">
<h4><span>2.3.5 Changes to the Debian files</span></h4>
<p>
To avoid to overwrite the generic deb created in the previous chapter,
we will rename this new deb package for Maemo. We will use 'myapp-mobile'.
To be consistent with the debhelper process, here the list of all this
concerned changes:
</p>
<ul>
<li>
<p>
In the <code>changelog</code> file, the line
<code>myapp (1.0-1) unstable; urgency=low</code> becomes
<code>myapp-mobile (1.0-1) unstable; urgency=low</code>
</p>
</li>
<li>
<p>
In the <code>control</code> file, the value for the
<code>Source</code> and <code>Package</code> fields is changed
to <code>myapp-mobile</code>
</p>
</li>
<li>
<p>
The file <code>myapp.links</code> is renamed as
<code>myapp-mobile.links</code>
</p>
</li>
</ul>
<p><strong>Other changes to the <code>control</code> file:</strong></p>
<p>
According to
<a href="http://wiki.maemo.org/Packaging/Guidelines#Sections" rel="external">this documentation</a>,
we must choose a <code><strong>Section</strong></code> in this list:
</p>
<ul>
<li><code>user/desktop</code></li>
<li><code>user/development</code></li>
<li><code>user/education</code></li>
<li><code>user/games</code></li>
<li><code>user/graphics</code></li>
<li><code>user/multimedia</code></li>
<li><code>user/navigation</code></li>
<li><code>user/network</code></li>
<li><code>user/office</code></li>
<li><code>user/science</code></li>
<li><code>user/system</code></li>
<li><code>user/utilities</code></li>
</ul>
<p>
We can add extra data to the control file, used to build the deb.
<br />
The first is <code><strong>XB-Maemo-Display-Name</strong>: MyApp</code> .
</p>
<p>
The second is a base64 icon, used by the application manager of Maemo,
<strong><code>XB-Maemo-Icon-26</code></strong>.
</p>
<p>
We will use a bash script to create this base64 value from the 48px png icon.
</p>
<p>First we need the <code>uuencode</code> program, on debian/ubuntu:</p>
<p><code class="code-xterm-root">apt-get install sharutils</code></p>
<p>
then, we create a Bash script named <code>build_base64.sh</code> to
convert a 48x48px png into the desired text value:
</p>
<pre>#!/bin/bash<br /><br />set -e<br /><br /># base64 conversion<br />uuencode -m icon48.png icon48.png &gt; icon48.txt<br /><br /># remove the first line (begin-base64 ...)<br />sed -i '1d' icon48.txt<br /><br /># and the last line (====)<br />sed -i '$d' icon48.txt<br /><br /># add 4 spaces at the beginning of each lines<br />sed -i "s/^/    /" icon48.txt<br /><br /># and add a blank line at the end of the file<br />echo '' &gt;&gt; icon48.txt</pre>
<p>
You can find this script into the <code>data/icons</code> folder of the
<code>samples_chapter_2.tar.gz</code> archive. To launch it (into the
icons folder):
</p>
<p><kbd class="code-xterm">sh build_base64.sh</kbd></p>
<p>
We can now use the content of icon48.txt as the value of
<code>XB-Maemo-Icon-26</code> in our control file.
</p>
</div>
<div class="howto-section">
<h4><span>2.3.6 Build the deb</span></h4>
<p>
And, that's all, we can create our deb like in the previous chapter.
</p>
<p>
I don't write here the <code>build_maemodeb.sh</code> script, it's
almost the same as the one to build the generic debian package. You'll
find it in the joined archive.
</p>
<ul class="code-xterm">
<li><pre>cd samples_chapter_2</pre></li>
<li><pre>sh ./build_maemodeb.sh</pre></li>
</ul>
<p><em>
Note: I suppose in this howto that we don't have compiled code in our app.
<br />
If this is not the case, we <strong>must</strong> use
<strong><a href="http://wiki.maemo.org/Documentation/Maemo_5_Developer_Guide/Development_Environment/Maemo_SDK#Scratchbox" rel="external">scratchbox</a></strong>
to compile, and we
<strong>must use scratchbox to build the deb</strong> too!
<br />
And, like in the
previous chapter, don't use the line <code>Architecture: all</code> in the
control file.
</em></p>
</div>
<div class="howto-navigator-bottom">
<div class="howto-previous"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/22/Distribuer-votre-appli-XULRunner-22-Empaqueter-un-deb" title="Aller au chapitre 2.2">&lt; chapitre précédent</a></div>
<div class="howto-next"><a href="http://joliclic.free.fr/blog/index.php?post/2011/05/24/Distribuer-votre-appli-XULRunner-24-Empaqueter-un-rpm" title="Aller au chapitre 2.4">chapitre suivant &gt;</a></div>
<div class="clearer">&nbsp;</div>
</div>
<div class="howto-author">
<p>Nicolas Martin</p>
</div>
<div class="howto-download-section">
<p>
You can download all the samples of this chapter 2 (Linux) in the
<a href="http://joliclic.free.fr/mozilla/howto/dist-xul-app/dl.php?id=current_sample_2" class="howto-download-archive">samples_chapter_2.tar.gz</a>
archive.
</p>
</div>
<div class="howto-credits">
<p><em>
The myapp application, from
<a href="https://developer.mozilla.org/en/getting_started_with_xulrunner" rel="external">developer.mozilla.org</a>
is in the <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a>.
</em></p>
<p><em>
The icon used is from the
<a href="http://tango.freedesktop.org" rel="external">Tango Desktop Project</a>,
and is in the <a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a>.
</em></p>
<p><em>
All added data, and sample files, of this chapter 2, are in the
<a href="http://wiki.creativecommons.org/Public_domain" rel="external">Public Domain</a> too.
</em></p>
</div>
<div class="howto-footer">
<p>
The content of this article
is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>
</p>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width: 0;" src="http://i.creativecommons.org/l/by-sa/3.0/80x15.png" /></a>
</div>
</div>]]></content:encoded>
</item>
     </rdf:RDF>

