Krzysztof Wesołowski Programowanie, elektronika, automatyka – doświadczenia i projekty

17sie/09

Usuwanie nieużywanych funkcji z programu

W trakcie tworzenia biblioteki do obsługi wyświetlacza 7 segmentowego (7 segmentów+kropka) doszedłem do wniosku,  że  najbardziej eleganckie rozwiązanie to stworzenie osobnego pliku C dla tej biblioteki, wraz z nagłówkami z prototypami funkcji jak i z konfiguracją. Niestety napisanie kilku funkcji ustawiających liczbę na wyświetlaczu spowodowało znaczny rozrost programu - nieużywane funkcje, często bardzo obszerne, trafiły do pliku *.o a następnie do wygenerowanego HEXa zajmując miejsce, pomimo iż nie wszystkie były używane.

Po przetrząśnięciu kawałka internetu znalazłem rozwiązanie, którego efekty są naprawdę znaczące (usunięcie zbędnych funkcji potrafi zaoszczędzić dużo miejsca gdy korzystamy z bibliotek zawierających funkcje na każdą okazję), i w związku z tym warte powtórzenia w wielu innych programach - pozwoli to uniknąć ręcznego usuwania nieużywanego kodu z "biblioteki".

Ustawienie kompilatora

Okno Project Properties z dodanym poleceniem ffunctions-sections

Okno Project Properties z dodanym poleceniem ffunctions-sections

Aby móc usuwać nieużywane funkcje, muszą one w pliku wynikowym kompilatora być odrębnymi częściami. Zachowanie takie wymusza dodatkowy argument w poleceniu kompilatora:

-ffunction-sections

Dodanie takiej komendy w projekcie przy użyciu Makefile:

CFLAGS += -ffunction-sections

Przy korzystaniu z Środowiska Eclipse dla AVR należy z kolei polecenie dodać w ustawieniach projektu.

Z menu Eclipse wybieramy Project -> Properties,
następnie odnajdujemy C/C++ build -> Settings.
I przy wybranym configu Release, w zakładce Tool Settings wybieramy Optimizations z zakładki AVR Compiler. W polu Other Optimizations flag dopisujemy nasze "-ffunction-sections"

Ustawienia linkera

Ustawienia projektu - włączenie gc-sections

Okno Project Properties z dodanym poleceniem gc-sections

Poprzednio dodane polecenie umieści każdą funkcję w osobnej części pamięci - sekcji. Teraz pozostaje poinformowanie linkera, iż sekcje nie używane mają zostać usunięte - umożliwia to polecenie przekazane do linkera -gc-sections (gc od garbage collector). Tego również można dokonać poprzez plik Makefile lub ustawienia projektu.

Dla Makefile wystarczająca modyfikacja to

-Wl,-gc-sections

Z kolei w Eclipse będąc już w Project -> Properties-> C/C++ build -> Settings ->(Release) Wchodzimy w zakładkę AVR C Linker->General, i dodajemy polecenie "-Wl,-gc-sections"

U mnie taka modyfikacja ustawień pozwoliła na przykład usunąć jedyną funkcję używającą arytmetyki zmiennoprzecinkowej, zamieniając 2,5kB programu w 600bajtów.

Komentarze (1) Trackbacks (1)
  1. Dokładnie tak samo można zrobić z danymi, które nigdzie nie są używane – „-fdata-sections”

    4\/3!!