SFML – Budowanie aplikacji

Budowanie aplikacji dla „klienta” oraz o linkowaniu statycznym i dynamicznym.

Hej, dzisiaj chciałbym się zająć pozornie trudnym tematem, który jak się okaże pod koniec wpisu jest trywialnie prostu.

Uwaga! Cały wpis poświęcam budowaniu pod kątem Windowsa, w przypadku Linuksa jest prościej ;)

Tło fabularne


Jakiś czas temu na [forum Pasji Informatyki] zauważyłem, że całkiem sporo osób ma problem z finalnym zbudowaniem swojej gry, tak aby można było ją uruchomić poza lokalnym środowiskiem IDE, czy też na komputerze osób nieposiadających biblioteki SFML.

Próba uruchomienia aplikacji poza IDE kończy się następująco:

Dzisiaj pokażę jak poradzić sobie z tą sytuacją.

Jak zbudować aplikację?


Sam przepis jest względnie uniwersalny i może dotyczyć każdego projektu. Jednakże w tym wpisie zajmiemy się konfiguracją specyficzną dla SFML, w gwoli ścisłości całość pokażę krok po kroku dla Visual Studio (kroki dla innych środowisk są analogiczne).

Do tego poradnika będzie nam potrzebne SFML, ja korzystam z wersji 64bitowej. Warto też mieć otwartą przed sobą [dokumentację], bo będziemy z niej korzystać.

Debug vs Release

Pierwsza rzecz jaką należy zauważyć przy wydawaniu aplikacji jest to, że środowiska zazwyczaj dają możliwość skompilować ją w dwóch konfiguracjach:

  • Debug
  • Release

W skrócie:

  • Debug służy do kompilowania aplikacji na czas testów, kompilator dodaje tutaj dodatkowe symbole pomagające przy debugowaniu;
  • Release jest wersją „dla klienta”, tzn nie posiada jemu niepotrzebnych symboli, ani dodatkowych komunikatów (dzięki czemu waży też mniej).

Jeżeli chcecie dostarczyć wasz produkt „klientowi”, to powinniście skorzystać z konfiguracji Release. Jeżeli podążaliście tutorialem z linku powyżej to powinniście mieć skonfigurowany SFML dla wszystkich konfiguracji.

Linkowanie dynamiczne vs statyczne

Kolejnym krokiem jest wybranie sposobu linkowania bibliotek. Każda z opcji ma swoje wady i zalety i pokrótce je tutaj przedstawię.

Linkowanie dynamiczne

Linkowanie dynamiczne cechuje się tym (dla klienta), że obok pliku wykonywalnego (.exe) są pliki bibliotek (.dll), które są wymagane do poprawnego działania aplikacji.

Co to oznacza oprócz powyższego faktu w praktyce?

  • + plik wykonywalny waży mniej,
  • + z tych samych plików bibliotek może korzystać wiele aplikacji,
  • – odrobinę wolniejsze uruchamianie.

W przypadku SFML aby zbudować aplikację dynamicznie należy:

  1. dodać makro „SFML_DYNAMIC” w Properties -> Configuration properties -> C/C++ -> Preprocessor
  2. w Properties -> Configuration properties -> Input -> Additional Dependencies  należy dodać biblioteki zbudowane pod linkowanie dynamiczne, a więc np.: sfml-graphics.lib, sfml-system.lib, sfml-window.lib (bez żadnych post-fixów).

Następnie należy przygotować folder zawierający potrzebne pliki do uruchomienia aplikacji, a więc:

  1. plik wykonywalny – po skompilowaniu znajduje się pod ścieżką: <project_root>\<arch>\Release, np: test_project\x64\Release\test.exe
  2. pliki dll, dla SFML istnieją w wersji przekompilowanej pod ścieżką: <SFML_root>\bin

Przykład gotowego folderu z wszystkimi potrzebnymi plikami znajduje się powyżej na screenie.

Linkowanie statyczne

Tutaj mamy odwrotną sytuację do poprzedniej, a więc nie potrzebujemy żadnych dodatkowych plików poza plikiem wykonywalnym, ponieważ biblioteki są „wtopione” w plik wykonywalny.

Cechy tego rozwiązania:

  • + nieco szybsze uruchomienie,
  • + łatwiejsza dystrybucja,
  • – większy rozmiar aplikacji,
  • – nieco większe zużycie zasobów (z tych samych bibliotek może korzystać tylko jeden program wykonywalny).

Aby zbudować aplikację statycznie należy:

  1. dodać makro „SFML_STATIC” w Properties -> Configuration properties -> C/C++ -> Preprocessor
  2. w Properties -> Configuration properties -> Input -> Additional Dependencies  należy dodać biblioteki zbudowane pod linkowanie statyczne, a więc np.: sfml-graphics-s.lib, sfml-system-s.lib, sfml-window-s.lib (z post-fixem „-s”); oprócz tego należy dodać wszystkie biblioteki [zależne], np: opengl32.lib, freetype.lib, jpeg.lib, winmm.lib

Dystrybucja programu odbywa się przez dostarczenie finalnego pliku „.exe” do klienta (nie trzeba dostarczać żadnych dodatkowych plików).

Kiedy linkować statycznie, kiedy dynamicznie?

Tutaj wszystko zależy od waszych preferencji i samego projektu. W moim odczuciu, aby linkować statycznie trzeba mieć dobry powód, na pewno darowałbym je sobie dla trybu Debug oraz sytuacji gdy często jesteśmy zmuszani do aktualizowania kodu programu, dzięki linkowaniu dynamicznemu musimy podmienić tylko zmieniane pliki, a nie wszystko jak to by było w przypadku linkowania statycznego.

Dociekliwych zachęcam do samodzielnej eksploracji tego tematu, bo tutaj jedynie napomknąłem o pewnych rzeczach ;)

Podsumowanie


Dzisiaj zgłębiliśmy „tajniki” budowania aplikacji SFML w wersji „dla klienta”. Mam nadzieję, że wpis jest przydatny, a samo budowanie programów stało się znacznie prostsze.

Tradycyjnie zachęcam do podzieleniem się tym wpisem ze swoimi znajomymi, a także zachęcam do systemu komentarzy oraz strony na facebook’u.

Code ON!


  • no125261

    Pod linkowaniem dynamicznym jest napisane
    „W przypadku SFML aby zbudować aplikację statycznie należy:”

  • kuadam

    Przyda sie 😀 Co najlepiej zrobic z np teksturam w jaki sposob najlepiej je dostarczac wraz z plikiem exe? W tym momencie musze recznie przenosic pliki do folderu z exe a moze visual ma jakas opcje by robic to automatycznie?

  • Najlepiej w wersji „tradycyjnej”, tzn jako dostarczony oddzielny plik. Mało kiedy pliki z zasobami do gry to coś więcej niż zip ze zmienionym rozszerzeniem.

    Aż tak często nie trzeba wszystkiego przenosić, ale możesz zdefiniować akcje „post-build”, a tam możesz choćby uruchamiać skrypt kopiujący wymagane pliki w dogodne dla ciebie miejsce ;)
    https://msdn.microsoft.com/pl-pl/library/aa833213(v=vs.100).aspx

    • kuadam

      Dzieki pisze wlasnie pierwsza gre w zyciu dlatego nie wiem jescze za duzo w tym temacie kazda rada jest bardzo przydatna 😀

  • Powodzenia!

  • Kukos

    Co masz na mysli pod:
    Dynamiczne libki = odrobine wolniejsze uruchamianie ?

    • Odwoływanie się do zewnętrznych zasobów -> musi ją znaleźć -> zmapować -> … https://msdn.microsoft.com/pl-pl/library/windows/desktop/ms684184(v=vs.85).aspx

      Zdaje się, że inicjalizacja nieco więcej kosztuje, Michał po szczegóły idź do docsów, ja średnio stoję z Windowsem ;)

      • Kukos

        Zadałem pytanie, nie dlatego ze ja tego nie wiem, ale dlatego by sie upewnic ze nie chcesz nas tutaj oklamac ;). Nie ma czegosc takiego jak koszt tylko i wylacznie inita apki, gdy mamy dolaczone dll, adresy musza byc mapowane na dynamiczny addr + staly offset libki, oznacza to ze potrzebuje caly czas czytac naglowek mojej binarki aby mapowac adres do call ( np technika PIC ), dodatkowo zauwazmy ze sam kod nie siedzi juz nam w szybko dostepnej RO sekcji text, oznacza to ze za kazdym razem robie kosztownego long jumpa, to troche przykre ze nie moge sobie przyspieszac kodu za pomoca attrybutu hot, ze nie moge korzystac z funkcji inline ( to ze wpisanie przed funkcja inline gowno robi to inna bajka, tutaj mam na mysli prawdziwy inline ). Dodatkowo dochodzi kwestia lazy loading, co oznacza ze kwestia mapowania uruchomi sie w runtimie. Podsumowujac libki typu shared sa wolniejsze przy KAZDYM wywolaniu funkcji a nie tylko podczas inita.

        • W żaden sposób nikogo we wpisie nie oszukuje (nawet uwzględniając lazy loading, który de facto można pominąć), tematem wpisu nie jest traktowanie o różnicach i cechach różnych typów linkowania, a budowanie aplikacji SFML (co wynika wprost z tytułu wpisu).

          Podana charakterystyka bazuje na tym co można znaleźć w sieci, a jak już wspomniałem nie wgłębiam się w to jak całość działa bezpośrednio, bo (powtórzę to raz jeszcze) celem wpisu było coś innego.

          Dla mnie twój powyższy komentarz jest trochę offtopowy, bo schodzi nieco za nisko w stosunku do zawartości wpisu.

          • Kukos

            Jasne, doskonale to rozumiem [ to jest offtop tak odlegly od arta jak omoplata od balachy :) ] , wlasnie o ta machine rozpowrzechniania wiedzy mi chodzilo :) Oczywiste jest to ze bierzesz materialy z manuali docow, ogolnie z sieci, wiadomo ze skoro Twoj blog jest popularny to ktos skorzysta z wiedzy zawartej we wpisie i nadal bedziemy powielac powiedzmy nie blad ale pewna malutka niezgodnosc z rzeczywistosia :) A tak moze machina sie nieco zatrzyma :D

            Caly czas czekam na arty typowo low-levelowe, w koncu wiedze z uczelni i z pracy masz na tyle duza ze spokojnie molglbys tutaj zrobic kurs na miare AKiSO z PPT

  • Xev

    Wieki już nie używam VC++, nadal trzeba ustawać opcje związane z Multi-Threaded/Multi-Threaded-Dll bo inaczej trzeba ciągnąć VC redisty czy teraz już się zakłada że każdy Windows je ma? ;)