Kompilacja – rozumiana w najszerszym sensie “budowania” wynikowej aplikacji – to najwyraźniej całkiem serious business. Używając wyłącznie jednego IDE (zwłaszcza gdy jest nim Visual Studio), można długo nie zdawać sobie z tego sprawy. W końcu jedną z funkcji środowisk programistycznych jest właśnie maksymalne uproszczenie tego procesu. Idealnie ze strony użytkownika wymagane jest tylko wydanie polecenia zbudowania projektu, a czasem – w przypadku budowania w tle – nawet i to nie jest potrzebne.
Nie zawsze jednak tak było i także obecnie nie zawsze proces kompilacji programu może być czymś, co uważamy za automatycznie załatwione. Wiedzą o tym zwłaszcza aktywni uczestnicy projektów open source, a szczególnie tych pisanych w językach bez jedynie słusznych IDE czy kompilatorów – takich jak C, C++ czy Java. Nic dziwnego, że właśnie z ich otoczenia wywodzą się systemy zautomatyzowanego budowania projektów.
Starym, wysłużonym i trochę już niedzisiejszym, ale wciąż szeroko używanym jest GNU Make. To z niego prawdopodobnie wywodzą się takie podstawowe koncepcje automatycznej kompilacji jak choćby target, czyli rodzaju “punktu wejścia” całego procesu. Dwa polecenia typowo służące zainstalowaniu programu ze źródeł na systemach linuksowych:
to właśnie wywołania GNU Make dla dwóch różnych targetów: domyślnego (uruchamiającego kompilację) i install
(wykonującego inne czynności instalacyjne). Między targetami występują acykliczne zależności, określające wymaganą kolejność przeprowadzania poszczególnych kroków procesu budowy, a także pozwalające na pominięcie tych, które nie są aktualnie potrzebne. Dla przykładu, domyślny target może zajmować się linkowaniem, więc do działania wymagać skompilowanych modułów. Zależeć wtedy będzie od targetów, które zajmują się właśnie kompilacją. Przy dobrze napisanym pliku makefile
wykonają się jedynie te odnoszące się do plików z kodem, w których faktycznie nastąpiły zmiany od czasu ostatniej budowy projektu.
Ponieważ zarówno składnia, jak i możliwości GNU Make (ograniczające się głównie do uruchamiania poleceń powłoki) pozostawiają wiele do życzenia, pojawiły się w końcu inne tego typu narzędzia. Potrzebowała ich głównie wieloplatformowa Java i stąd wziął się Apache Ant (skrót od Another Neat Tool). Nie straszy on już składnią opartą na tabulatorach; zamiast tego straszy XML-em ;-) Mimo większej przenośności międzysystemowej (abstrakcja operacji na plikach i katalogach) nadal brakuje mu jednak uniwersalności językowej, która zresztą nie wydaje się wcale celem istnienia Anta. Pomimo wyraźnego zorientowania na Javę da się go jednak z powodzeniem używać w projektach pisanych również w innych językach.
Te dwa rozwiązania to oczywiście nie jedyne systemy automatycznego budowania, z którymi możemy się spotkać. Z innych ciekawe są chociażby CMake czy Apache Maven. Warto się z nimi zapoznać, by na widok paczki, która oprócz kodu zawiera tylko plik build.xml
lub makefile
nie wpadać w popłoch :)
CMake jest o tyle fajny, że nie odpowiada sam za budowę binarki, a produkuje plik projektu, skrypt budujący na różne platformy/IDE. Warto się nim pobawić, bo niewielkim nakładem pracy zyskujemy całkiem fajny automat i uniezależniamy się od jakiegokolwiek środowiska (jak się ktoś uprze jest w stanie wypluć skrypty na dość specyficzne platformy, np. iPhone).
Kiedyś (nad)używałem make. Niestety jego możliwości są dość ograniczone i wymagają pisania sporej ilości kodu.
Od dłuższego czasu używam SCons i bardzo polecam to narzędzie. W szczególności pliki konfiguracyjne pisze się w normalnym języku (Python) co daje większą elastyczność. Co więcej – coś co w make zajmowało kilkadziesiąt linijek w scons można uzyskać trzema (w Makefile trzeba ręcznie wpisywać zależności między plikami projektu albo kombinować z G++ -MM).
@lmmilewski Możesz rozwinąć ten temat?
Ja osobiscie, nie tylko do multiplatformowych projektow, uzywam bakefile’sa. Trzymanie opisu projektu w pliku xml i podbnie jak cmake generowanie dedykwoanych skryptow/plikow projektu poszczegolnym narzedziom/IDE ;)
SCons <3 Fajny, oparty na pythonie, zorientowany obiektowo, wygodny (mało pisania dla prostych rzeczy) i łatwy do rozszerzenia.