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".

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

0 nowych
januszek   19 #1 13.07.2011 14:35

Napisałeś tak, jakbyś opisywał pokutę - mimo tego, że temat jest dosyć ciekawy. Dlaczego zrezygnowałeś z użycia py2exe lub cx_Freeze?

ps. NSIS jest programem open source. Co stoi na przeszkodzie żebyś wykonał swojego forka, który będzie bardziej developer-friendly?

webnull   9 #2 13.07.2011 15:57

@januszek | 13.07.2011 14:35
Jak byś czytał dalej serię to byś wiedział, że użyłem cx_Freeze.

Ryan   15 #3 13.07.2011 18:45

Nie czaję dlaczego użyłeś NSIS, a nie natywnego windowsowego instalatora MSI. To trochę tak, jakbyś dystrybuował na Debiana paczki jako samorozpakowującą się binarkę, a nie deba. Dziwne to, szczególnie, że jest masa narzędzi do tworzenia MSI (darmowych i komercyjnych), w tym wbudowany w Visual Studio generator paczek instalacyjnych.

webnull   9 #4 13.07.2011 19:39

@Ryan (redakcja) | 13.07.2011 18:45
Widocznie pierwsze kilka wyników w Google pod hasłem podobnym do "windows build installer" wskazywało tylko na NSIS oraz komercyjne rozwiązania...

Ryan   15 #5 13.07.2011 21:14

Bo Google jest anty-MS. ;] A bardziej poważnie: niestety najlepsze programy do tworzenia MSI są faktycznie płatne (Wise, InstallShield). Ale bezpłatne też dają radę (VS, WiX).

webnull   9 #6 13.07.2011 22:16

@Ryan (redakcja) | 13.07.2011 21:14
W takim razie szkoda, że nie słyszałem o "VS" i "WiX".

NSIS się nieźle reklamuje, bardzo wiele aplikacji go używa - szczególnie tych opensource'owych.

Ryan   15 #7 14.07.2011 12:39

VS = Visual Studio. Przypuszczam, że jednak słyszałeś. ;)

Z NSIS jest tak, że przez dłuższy czas darmowe narzędzia do tworzenia MSI zasysały na całej linii. Dość powiedzieć, że dostarczany z SDK szrot był tak nieintuicyjny, że łatwiej było wziąć istniejące MSI i przerobić je sobie, niż stworzyć nowe od zera. :S NSIS "wygrało" przez inercję.

przemo_li   11 #8 14.07.2011 19:16

@Ryan

VS do paczkownia skryptów pythonowych ??? WoW

Zapodaj jakiegoś linka!

PS VS Ekspress to kobyła, naprawdę polecasz instalację tego środowiska dla jednego instalatora? A może wystarczy tylko coś małego zainstalować.

Ryan   15 #9 14.07.2011 20:11

Skoro mogę w VS wyklikać instalator z samymi plikami tekstowymi, to dlaczego skrypty w Pythonie (szczególnie, że webnull stworzył exe) miałyby się nie poddać?

A "kobyłę" warto zainstalować choćby po to, by zobaczyć jak wygląda najpopularniejsze na świecie IDE. ;>

  #10 15.07.2011 00:56

Kobyła? VisualStudio w stosunku do Eclipse to demon prędkości.

  #11 18.07.2011 00:52

Bardziej podobne do PKGBUILDów są w Windowsie pliki inf, tylko nie wiem czy ktoś jeszcze ich używa. Dokumentacja do nich nigdy nie była jakaś super, ale jak umiesz, to robisz instalator (i deinstalator o ile pamiętam) kilkoma linijkami + lista plików/wpisów w rejestrze.

  #12 18.07.2011 09:23

Po cholerę ci ten nsis jeśli tak go nie lubisz? I jaki brak alternatyw? Znów wychodzi twoja niewiedza: InnoSetup darmowy i bardzo dobry, instalator z VisualStudio albo nawet z całkowicie darmowego SharpDevelop (oba to MSI). Do wyboru do koloru.

januszek   19 #13 18.07.2011 14:14

@webnull: Po pierwsze: komentowałem cz.3 "Pakowanie projektu w instalator NSIS" - bo ten odcinek przeczytałem pierwszy (kliknąłem w link na głównej dp). Nie przyszło mi wtedy do głowy, że to cały serial wyemitowany na raz, w którym logiczne fragmenty są pofragmentowane na różne odcinki ;)
Po drugie: skoro użyłeś cx_Freeze to efektem tego powinno być to, że masz katalog \dist, w którym masz swoją aplikację i wszystko co potrzebne do jej działania. Pakujesz to wszystko zipem i już (moim zdaniem lepiej dla usera jak sobie sam rozpakuje pliki z zipa niż kiedy instalator jest przygotowany na pół gwizdka).
Jeśli instalator jest konieczny to możesz użyć zip-a a w w NSIS wybierasz opcję "Installer based on ZIP file" i nie musisz sobie głowy zawracać rekurencyjnym przyłączaniem katalogów. Edytujesz jeszcze tylko skrypt w ../NSIS/Contrib/zip2exe/ i masz po sprawie.
Kilka uwag do tej aplikacji, którą przetestowałem w WinXP i Win7: Jeśli dopisujesz coś do menu kontekstowego to warto zapytać wcześniej usera czy tego chce. Powinna być też możliwość usunięcia tego. Jeśli masz instalator to powinny być tam i opcje odinstalowania aplikacji oraz aktualizacji programu (czyli np instalator nowszej wersji sam odinstaluje wersje wcześniejsze na etapie instalacji) - domyślam się, że wtedy skrypty NSIS-a były bardziej złożone niż Twój subget? Co do samego programy, w 7 działa, w XP się sypie - vide: http://42.pl/u/2D8x