Strona używa cookies (ciasteczek). Dowiedz się więcej o celu ich używania i zmianach ustawień. Korzystając ze strony wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki.    X

cz.3| Jak to jest być deweloperem aplikacji wieloplatformowej - Deweloper vs Windows

Witam.

Tematem tego wpisu będą moje doświadczenia z instalatorem NSIS podczas budowania instalatora dla aplikacji napisanej w Pythonie.

3. Pakowanie projektu w instalator NSIS

Zrozumienie działania instalatora NSIS zajęło mi sporo czasu, a wskazówki na najbardziej podstawowe pytania były bezużyteczne. Ludzie zadawali masę pytań na forach na jeden nurtujący wszystkich problem - "jak skopiować więcej niż jeden plik".

r   e   k   l   a   m   a

Niby z NSISa korzysta Pidgin, Winamp i masa innych popularnych aplikacji jednak wydaje mi się, że ten instalator jest tak szeroko wykorzystywany tylko ze względu na ogólny brak alternatyw. Są alternatywy, niektóre z nich płatne, a niektóre mają zbyt małe możliwości.

1) Jak dodać pliki i katalogi projektu rekursywnie

Szukałem godzinami odpowiedzi na to pytanie, jednak trudno było znaleźć konkretną odpowiedź dlatego wymyśliłem prosty skrypt w Pythonie generujący listę plików i katalogów do zarchiwizowania przez instalator.

Listing nsi-paths-build.py

#!/usr/bin/python2
import os

commands = ""
originalDirectory = "c:\\subget\\build\\exe.win32-2.7"

def sortItemsByDirectory(items, directory):
    directories = list()
    allItems = list()

    # first files
    for item in items:
        if os.path.isdir(directory+"\\"+item):
            directories.append(item)
        else:
            allItems.append(item)

    item = ""

    # and then directories
    for item in directories:
       allItems.append(item)

    return allItems 

def generateList(directory):
    global commands, originalDirectory

    items = os.listdir(directory)

    for item in items:
        if os.path.isdir(directory+"\\"+item):
            #print "\n  CreateDirectory "+directory+"\\"+item+"\n  SetOutPath "+directory+"\\"+item
            cd = directory+"\\"+item
            commands += "\n  CreateDirectory "+directory+"\\"+item+"\n  SetOutPath "+cd.replace(originalDirectory, '$INSTDIR')
            generateList(directory+"\\"+item)

            continue
        elif os.path.isfile(directory+"\\"+item):
            #print "\n  File "+directory+"\\"+item
            commands += "\n  File "+directory+"\\"+item

print "Generating file list..."
generateList(originalDirectory)

#print fileList

print "Opening template..."
Template = open("f:\\subget\\windows\installer-template.nsi", "rb")
TemplateCode = Template.read().replace("{#INSTALLER_FILES}", commands)
Template.close()

print "Saving installer script..."
Installer = open("f:\\subget\\windows\\installer.nsi", "wb")
Installer.write(TemplateCode)
Installer.close()

Skrypt ten otwiera szablon skryptu instalatora i zamienia w nim wyrażenie {#INSTALLER_FILES} na listę plików które instalator powinien uwzględnić przy budowaniu.

Fragment listingu installer-template.nsi


OptionsOK:
  CreateDirectory "$INSTDIR"
  SetOutPath "$INSTDIR"

  {#INSTALLER_FILES}
  ;CopyFiles "c:\subget\build\exe.win32-2.7\*.*" "$INSTDIR"
  WriteRegStr HKCU "SOFTWARE\Subget" 'Directory' '$INSTDIR'
  WriteRegStr HKCR "AVIFile\shell\Pobierz napisy\command" "" "$INSTDIR\subget.exe $\"%1$\""
  WriteRegStr HKCR "mpgfile\shell\Pobierz napisy\command" "" "$INSTDIR\subget.exe $\"%1$\""
  WriteRegStr HKCR "mpegfile\shell\Pobierz napisy\command" "" "$INSTDIR\subget.exe $\"%1$\""
  WriteRegStr HKCR "mp4file\shell\Pobierz napisy\command" "" "$INSTDIR\subget.exe $\"%1$\""
  WriteRegStr HKCR "3gpfile\shell\Pobierz napisy\command" "" "$INSTDIR\subget.exe $\"%1$\""
SectionEnd

Przykładowe dane generowane przez skrypt nsi-paths-build.py

File c:\subget\build\exe.win32-2.7\select.pyd
  File c:\subget\build\exe.win32-2.7\subget.exe
  File c:\subget\build\exe.win32-2.7\unicodedata.pyd
  CreateDirectory c:\subget\build\exe.win32-2.7\usr
  SetOutPath $INSTDIR\usr
  CreateDirectory c:\subget\build\exe.win32-2.7\usr\share
  SetOutPath $INSTDIR\usr\share
  CreateDirectory c:\subget\build\exe.win32-2.7\usr\share\alang
  SetOutPath $INSTDIR\usr\share\alang
  CreateDirectory c:\subget\build\exe.win32-2.7\usr\share\alang\python
  SetOutPath $INSTDIR\usr\share\alang\python
  File c:\subget\build\exe.win32-2.7\usr\share\alang\python\alang.py
  File c:\subget\build\exe.win32-2.7\usr\share\alang\python\__init__.py
  CreateDirectory c:\subget\build\exe.win32-2.7\usr\share\alang\translations
  SetOutPath $INSTDIR\usr\share\alang\translations
  CreateDirectory c:\subget\build\exe.win32-2.7\usr\share\alang\translations\english
  SetOutPath $INSTDIR\usr\share\alang\translations\english
  File c:\subget\build\exe.win32-2.7\usr\share\alang\translations\english\subget.py
  File c:\subget\build\exe.win32-2.7\usr\share\alang\translations\english\__init__.py

Teraz pytanie, zapewne retoryczne bo deweloperzy NSIS mi raczej tu nie odpowiedzą ale zadam je - dlaczego NSIS nie obsługuje rekurencyjnego przyłączania całych katalogów? Po co się tyle trudzić żeby zapakować coś w instalator... litości!

W systemach Uniksowych budowanie takiego instalatora jest robotą na maksimum 5 minut, szkoda, że pod Windows człowiek tyle musi się namęczyć.

2) Systemy Uniksowe a instalatory (paczki)

W Arch Linux czy w Gentoo wystarczy w zasadzie pobrać jeden z setek tysięcy gotowych skryptów, zmienić nazwę pakietu, adres źródłowy skąd można pobrać pakiet, wersję i wpisać jedno polecenie które zbuduje pakiet.

- Dokumentacja PKGBUILD w Arch Linux
- Polska dokumentacja budowania pakietów dla Arch Linux
- Zbiór setek tysięcy gotowych PKGBUILDów z Arch Linux
- Ebuildy w Gentoo, nawet po polsku dokumentacja i jaka czytelna!

Jeszcze raz powtórzę pytanie: Dlaczego w Windows trzeba się tle namęczyć? Czy to na prawdę konieczne? 

Komentarze