WxWidgets to jeden z zestawów bibliotek pozwalający na tworzenie multiplatformowych aplikacji okienkowych. Najprostszym sposobem by zacząć pracę z wx jest zaopatrzenie się w Code::Blocks, który dodatkowo posiada dedykowany WYSIWYG do okienek o nazwie wxSmith. Jako że pożegnałem się z c::b na zawsze (albo przynajmniej taki miałem zamysł), pora przygotować sobie środowisko pod VSCode.
Instalacja wxWidgets
Po ściągnięciu paczki stąd (Development jak się bawisz, Stable jak piszesz coś poważniejszego) zainstaluj paczkę w wybranym folderze. Naiwny pomyślałby, że na tym zabawa się kończy. Otóż nie – ściągnięta paczka to tylko zestaw źródeł wx, trzeba je jeszcze skompilować, o czym powstał cały artykuł na oficjalnym wiki. Są oczywiście prekompilowane paczki, ale dość stare, zatem nie ma co się bać i robić swoje. Jako że mam TDM-GCC 5.1 wskazane komendy budowania nie zadziałały, zatem zgodnie z działem Troubleshooting zadziałała dopiero komenda:
mingw32-make SHELL=CMD.exe -j4 -f makefile.gcc BUILD=release UNICODE=1 SHARED=0 MONOLITHIC=1 CXXFLAGS="-fno-keep-inline-dllexport -std=gnu++11"
Na tym zabawa się nie skończyła, gdyż spotkał mnie komunikat: gcc_swu\monolib_gdicmn.o: No such file or directory . Po chwili guglania okazało się, że komenda kompilacji jest za długa, zatem musiałem ją skrócić o parametry SHELL=CMD.exe -j4 . Polecam zrobić to w ostatnim kroku, gdyż parametr -j4 decyduje o liczbie rdzeni użytej podczas kompilacji.
Wszystko fajnie, ale podczas kompilacji przykładowego kodu wyrzucało mi pełno błędów z rodziny undefined reference to … . Poczytałem trochę i okazało się, że sposób budowy MONOLITHIC jest niezalecany. Dodatkowo, flaga UNICODE już jest zbędna, jako że wersja ANSI została porzucona. Zatem ostateczne komendy do wstukania to:
mingw32-make -f makefile.gcc SHARED=0 BUILD=release clean mingw32-make SHELL=CMD.exe -j4 -f makefile.gcc BUILD=release SHARED=0 CXXFLAGS="-fno-keep-inline-dllexport -std=gnu++11"
Dodatkowo, aby uniknąć warningów podczas budowania projektów opartych o wxWidgets, w include\wx\msw\setup.h należy zdefiniować wszystkie wpisy WXWIN_COMPATIBILITY_ na zero.
Sprzężenie z CMake
Pisanie makefile’i nie należy do najprzyjemniejszych zajęć. Z tego względu powstał CMake, w którym w wygodniejszej składni pisze się makefile makefile’a. 😉 Narzędzie to dość mocno się upowszechniło i stało się silnym standardem w różnej maści otwartych projektach.
Jedną z zalet CMake jest możliwość zlecenia mu automatycznego znalezienia bibliotek popularniejszych pakietów. Niestety skrypt od wxWidgets nie jest najwybitniejszy, dlatego CMake’owi trzeba trochę pomóc. W pliku cmake/share/cmake-3.8/Modules/FindwxWidgets.cmake znalazłem fragment kodu odpowiedzialny za znajdowanie instalacji wx:
find_path(wxWidgets_ROOT_DIR NAMES include/wx/wx.h PATHS ENV wxWidgets_ROOT_DIR ENV WXWIN "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\wxWidgets_is1;Inno Setup: App Path]" # WX 2.6.x C:/ D:/ ENV ProgramFiles PATH_SUFFIXES wxWidgets-3.1.0 wxWidgets-3.0.2 wxWidgets-3.0.1 wxWidgets-3.0.0
Jak widać, wx szukany jest w katalogu głównym dysku C lub D. Jeśli zainstalowałeś go w miejscu nietypowym, musisz posiłkować się zmienną środowiskową WXWIN. Dodatkowo, posiadając wydanie 3.0.3 skrypt nie znajdzie poprawnego miejsca instalacji. Dodanie linii wxWidgets-3.0.3 naprawi tę bolączkę.
Po tym wszystkim pozostaje dodać obsługę wxWidgets do CMake’a projektu. Załatwią to poniższe linie zgodne z tutkiem na stronie wx:
# wxWidgets find_package(wxWidgets REQUIRED gl core base adv) include(${wxWidgets_USE_FILE}) add_executable(app ${sources}) set_target_properties(app PROPERTIES LINKER_LANGUAGE CXX) # and for each of your dependent executable/library targets: target_link_libraries(app ${wxWidgets_LIBRARIES})
Konfiguracja VSCode
Ten krok jest banalny z racji gotowego rozszerzenia CMake, które na dolnej belce dodaje wybór trybu budowania i przycisk „Build”. Z nieznanego mi powodu moje aplikacje lubią się crashować przy CMake’owym targecie debug, ale na chwilę obecną mi to nie przeszkadza. Include i browse paths należy skonfigurować w sposób podobny do poniższego:
[ "D:/prg/kompilatory/TDM-GCC/include", "D:/prg/kompilatory/TDM-GCC/lib/gcc/mingw32/5.1.0/include", "D:/prg/kompilatory/TDM-GCC/lib/gcc/mingw32/5.1.0/include/c++", "D:/prg/kompilatory/TDM-GCC/lib/gcc/mingw32/5.1.0/include/c++/mingw32", "D:/prg/kompilatory/TDM-GCC/lib/gcc/mingw32/5.1.0/include/c++/tr1", "D:/prg/kompilatory/TDM-GCC/include", "D:/prg/libs/wxWidgets-3.0.3/include", "D:/prg/libs/wxWidgets-3.0.3/lib/gcc_lib/mswu" ]