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:

Call graph

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):

  1. Instalujemy Doxygen i Graphviz: sudo apt-get install doxygen graphviz
  2. Wchodzimy do katalogu, w którym mamy nasz kod źródłowy
  3. Odpalamy doxygen -g. To wygeneruje nam plik konfiguracyjny Doxyfile
  4. 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
  5. Generujemy dokumentację z grafami wywołań: doxygen Doxyfile
  6. 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 postaciWinMain -> 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 :)

Related Posts: