Ostatnio przyszło mi pracować z naprawdę fajnym kodem C++, odpowiedzialnym za abstrakcję hardware’u w, bądź co bądź, oprogramowaniu sprzedawanym na całym świecie za grube miliony…
Najbardziej spodobała mi się pewna klasa, która reprezentowała…wszystko, i pozwalała na zrobienie w zasadzie wszystkiego ze sprzętem, który interfejsowała. 160 metod składowych, 7’000 linii kodu… no marzenie :)
Po trzech dniach wgryzania się w kod i pokryciu 8 stron A4 notatkami i diagramami pomyślałem, że przydałby mi się program, który wygenerowałby… graf wywołań funkcji. Tak, żebym mógł w miarę łatwo ogarnąć jak te 160 funkcji współpracuje ze sobą.
Już miałem pomysł na parsowanie gramatyki C++ z wykorzystaniem własnoręcznie napisanego kompilatora w javacc, już prawie odpalałem eclipsa, gdy pojawiła się myśl “hola hola! Takie coś musiał już ktoś przecież zrobić!” No i jak się okazało – ktoś już taki program zrobił :)
Zacznijmy od końca – przykładowy graf
Do potrzeb demonstracji odkopałem mój leciwy projekcik w OpenGl renderujący siatkę terenu i przepuściłem przez generator grafów. Dla funkcji ApplicationInitialize udało mi się uzyskać taki graf:
Od razu mamy pogląd na to, co się w programie dzieje, prawda? :)
(BTW. wiem, że nie wygląda to na majstersztyk sztuki programowania ale – ten programik napisałem całe wieki temu).
Jak wygenerować graf
Wykorzystamy do tego system dokumentacji kodu Doxygen + generator grafów Graphviz. W zasadzie to wygenerujemy kompletną dokumentację programu, w której do opisów funkcji po prostu dołączone zostaną grafy wywołań. Po kolei, co robimy (wersja dla Ubuntu):
-
Instalujemy Doxygen i Graphviz: sudo apt-get install doxygen graphviz
-
Wchodzimy do katalogu, w którym mamy nasz kod źródłowy
-
Odpalamy doxygen -g. To wygeneruje nam plik konfiguracyjny Doxyfile
-
Modyfikujemy w pliku Doxyfile:
HAVE_DOT = YES # aplikacja "dot" z pakietu Graphviz jest zainstalowana
CALL_GRAPH = YES # generuj grafy wywołań narzędziem "dot"
RECURSIVE = YES # rekurencyjnie przeszukuj podkatalogi z kodem źródłowym
EXTRACT_ALL = YES # dokumentuj również funkcje bez komentarzy doxygena
EXTRACT_PRIVATE = YES # dokumentuj funkcje prywatne
EXTRACT_STATIC = YES # dokumentuj funkcje statyczne
-
Generujemy dokumentację z grafami wywołań: doxygen Doxyfile
-
W katalogu html mamy naszą dokumentację z grafami :)
Uwaga
Za kulisami działa to tak, że Doxygen generuje kod w języku dot, reprezentujący schematy zależności w postaci “WinMain -> CreateWindow“, czyli WinMain wywołuje CreateWindow. Kod ten jest przekazywany do programu “dot”, który to generuje nam ładne obrazki PNG z grafami. Dlatego jeśli zdarzyło Ci się, że nie widzisz grafów w wygenerowanej dokumentacji – sprawdź, czy masz zainstalowaną aplikację dot z pakietu Graphviz (np. poleceniem which dot).
Na koniec – bonus
Warto jeszcze wiedzieć o tym, że oprócz C++, Doxygen generuje dokumentację również dla C# i Javy, a przy tym obsługuje składnię Javadoc. Tak więc możemy całkiem łatwo wygenerować sobie dokumentację z grafami dla projektu Javowego.
Druga rzecz – w przeciwieństwie do mojego diagramu powyżej, wygenerowane diagramy są “nawigowalne” – można klikać po funkcjach i przenosi Cię do opisu funkcji w dokumentacji :)