Forum: Compiler & IDEs #if innerhalb eins #defines


von Malte _. (malte) Benutzerseite


Lesenswert?

Hallo,
ich habe hier einen Quellcode, der je nach gewünschten Features 
unterschiedlich zusammengebaut werden soll - unter anderem um auf einem 
Mikrocontroller nicht unnötig Platz und Rechenzeit zu verschwenden.

Am besten funktioniert dafür
1
#ifdef MENU_TEXT_ENABLE_5X5
2
  #if (MENU_TEXT_FONT_CLASSES > 1)
3
    #define MENU_CHECK_FONT_5X5_START if ((font >= 12) && (font <= 15)) {
4
  #else
5
    #define MENU_CHECK_FONT_5X5_START {
6
  #endif
7
#else
8
  #define MENU_CHECK_FONT_5X5_START if (0) {
9
#endif
10
11
#define MENU_CHECK_FONT_5X5_END }
12
13
#ifdef MENU_TEXT_ENABLE_5X7
14
  #if (MENU_TEXT_FONT_CLASSES > 1)
15
    #define MENU_CHECK_FONT_5X7_START if (font <= 3) {
16
    #define MENU_CHECK_FONT_5X7_END }
17
  #else
18
    #define MENU_CHECK_FONT_5X7_START {
19
    #define MENU_CHECK_FONT_5X7_END }
20
  #endif
21
#else
22
  #define MENU_CHECK_FONT_5X7_START if (0) {
23
  #define MENU_CHECK_FONT_5X7_END }
24
#endif
25
26
#ifdef MENU_TEXT_ENABLE_8X15
27
  #if (MENU_TEXT_FONT_CLASSES > 1)
28
    #define MENU_CHECK_FONT_8X15_START if ((font >= 4) && (font <= 8)) {
29
  #else
30
    #define MENU_CHECK_FONT_8X15_START {
31
  #endif
32
#else
33
  #define MENU_CHECK_FONT_8X15_START if (0) {
34
#endif
35
36
#define MENU_CHECK_FONT_8X15_END }

Also je nach dem welcher Font, und vor allem ob mehr als einer, 
verwendet wird, wird der Quellcode unterschiedlich zusammen gebaut.
Das führt aber bei einem nicht benutzten Font bei folgendem Code zu 
Problemen:
1
MENU_CHECK_FONT_5X5_START
2
    bmpsource = &(characters_5x5[MENU_TEXT_5X5_BYTES * cdraw]);
3
MENU_CHECK_FONT_5X5_END
4
MENU_CHECK_FONT_5X7_START
5
    bmpsource = &(characters_5x7[MENU_TEXT_5X7_BYTES * cdraw]);
6
MENU_CHECK_FONT_5X7_END
7
MENU_CHECK_FONT_8X15_START
8
    bmpsource = &(characters_8x15[MENU_TEXT_8X15_BYTES * cdraw]);
9
MENU_CHECK_FONT_8X15_END
Wenn ein Font nicht definiert ist und somit dass array, z.B. 
characters_5x7 auch nicht vorhanden ist, ist das Programm nicht korrekt 
- obwohl der Compiler den Zugriff dank if (0) weg optimieren wird.
Was ich eigentlich bräuchte wäre also ein
1
#ifdef MENU_TEXT_ENABLE_5X7
2
  #if (MENU_TEXT_FONT_CLASSES > 1)
3
    #define MENU_CHECK_FONT_5X7_START if (font <= 3) {
4
    #define MENU_CHECK_FONT_5X7_END }
5
  #else
6
    #define MENU_CHECK_FONT_5X7_START {
7
    #define MENU_CHECK_FONT_5X7_END }
8
  #endif
9
#else
10
  #define MENU_CHECK_FONT_5X7_START #if 0
11
  #define MENU_CHECK_FONT_5X7_END #endif
12
#endif
Aber das geht leider nicht. Oder gibt es doch eine Möglichkeit?
Notfalls muss ich auch &(characters_5x7[MENU_TEXT_5X7_BYTES * cdraw]); 
durch ein Makro ersetzen, welches dann je nach bedarf das passende Array 
oder NULL ist.

: Bearbeitet durch User
von Sven B. (scummos)


Lesenswert?

Uargh. Muss das wirklich sein? Wenn zur Compile-Zeit klar ist, dass ein 
Ausdruck in einem if falsch ist, wirft der Compiler den Code eh weg ... 
so schlau sind die schon. Da brauchst du nicht diesen Makro-Dschungel 
bauen ... schon gar nicht, um 5 Byte Codegröße zu sparen.

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Ist ja mega umständlich! Deklariere alle Fonts einzeln als 
globale/statische Variablen. Dann machst du ein globales Array welches 
Pointer auf die gewünschten Fonts enthält. Das kann man auch simpel per 
Makros machen:
1
static const Font font1 { ... }, font2 { ... }, font3 { ... }, font4 { ... };
2
3
#define ENABLED_FONTS font1,font2,font3
4
const Font* fonts [] = { ENABLED_FONTS, NULL };
Dieses Array kannst du dann nach belieben iterieren.
Nicht verwendete Fonts werden vom Compiler schlicht wegoptimiert. 
Ansonsten schließe ich mich Sven an.

von I <3 Makefiles (Gast)


Lesenswert?

ein weiterer Ansatz ist die Auswahl an Parameter und Codeabschnitte 
(=Quelldateien) ausserhalb zu regeln.
Im Makefile kann vor dem Kompilieren in einem (Temporären) Verzeichnis 
das zusammenkopiert werden was für eine gewünschte Buildvariante 
benötigt ist.
Vor dem Kopilieren kann auch ein Stück Quellcode variantenspezifisch 
generiert werden, z.b. eine explizite #include-Liste.

Bei so organisierten Projekte tut man allerdings gut daran, buildlogs 
(oder extrakt davon) aufzubewahren, damit danach jederzeit die Binaries 
zugeordnet werden können (z.B. per SHA1/MD5 Prüfsumme oder eine andere 
"Signatur", welche natürlich beim builden mitgeloggt werden muss)

von W.S. (Gast)


Lesenswert?

Malte _. schrieb:
> Also je nach dem welcher Font, und vor allem ob mehr als einer,
> verwendet wird, wird der Quellcode unterschiedlich zusammen gebaut.

Baue einfach nicht hinein, was du nicht brauchst oder nimm einen Chip 
mit genügend Platz im Flash.

Solche Definier-Orgien sind mir ein Graus und sie sind ein netter 
Ansatz, um sich selbst Probleme zu machen. Wer hindert dich eigentlich 
daran, dein Gdi projektspezifisch zu machen und dort nur das einzubauen, 
was du tatsächlich benötigst?

W.S.

von Hosenmatz (Gast)


Lesenswert?

Das ist nicht nur: "Aua!" sondern schon "Au weia!".

Sozusagen das programmatische Äquivalent zu Kurt Bindl und dem Stefan 
Hackebusch.

Kein Mensch, der noch alle Tüten in der Schüssel hat programmiert so. 
Und im professionellen Umfeld kriegst Du Berufsverbot.

OK. Schluss mit lustig.


Es mag mühsam sein, aber vielleicht schreibst Du hier mal Deine 
Anforderungen detailliert auf und wir überlegen zusammen, wie man das 
vernünftig machen kann.

von Malte _. (malte) Benutzerseite


Lesenswert?

W.S. schrieb:

> Baue einfach nicht hinein, was du nicht brauchst
Genau das versuche ich ja automatisiert zu erreichen ;)
>
> Solche Definier-Orgien sind mir ein Graus und sie sind ein netter
> Ansatz, um sich selbst Probleme zu machen.
Jep, und weil es mir selbst nicht gefällt frage ich hier ja nach einer 
besseren Lösung.


Hostenmatz schriebt:
> Es mag mühsam sein, aber vielleicht schreibst Du hier mal Deine
> Anforderungen detailliert

Es geht um mein Projekt:
Beitrag "Menu Designer für Grafik LCDs inklusive grafischem Editor"
In dem möchte ich die derzeit separaten Dateien mit verschiedenen Fonts 
(und entsprechend doppelt zu watenden Code) vereinheitlichen (und habe 
UTF-8 Support eingebaut).

Der Benutzer kann relativ einfach in einem Editor einen Font auswählen 
und der Editor baut daraus passende Defines, die anzeigen welcher Font 
tatsächlich verwendet wird. Natürlich könnte ich kurzerhand alle 
Fontvarianten im Quellcode abdecken, aber dann würde ich genau den weg 
gehen, den leider so viele Bibliotheken gehen - sie werden von Version 
zu Version größer und langsamer ohne dass wirklich die Features benötigt 
werden. Daher mein Ansatz direkt zur Compilezeit unnützen Code zu 
entfernen.

> Und im professionellen Umfeld kriegst Du Berufsverbot.
Zu spät ;)

von Hosenmatz (Gast)


Lesenswert?

Malte _. schrieb:
> [...]
>
> Hostenmatz schriebt:
>> Es mag mühsam sein, aber vielleicht schreibst Du hier mal Deine
>> Anforderungen detailliert
>
> Es geht um mein Projekt:
> Beitrag "Menu Designer für Grafik LCDs inklusive grafischem Editor"
> In dem möchte ich die derzeit separaten Dateien mit verschiedenen Fonts
> (und entsprechend doppelt zu watenden Code) vereinheitlichen (und habe
> UTF-8 Support eingebaut).
Das mag so sein. Aber ich lese mir jetzt nicht den Thread durch, um das 
heraus zu suchen, was Dir Probleme beim Design macht. Ich sehe zwar ein 
kleines How-To für Anfänger, aber keine "Entwicklungsdokumentation" in 
der die Funktionsweise im Gesamtzusammenhang und im Detail erklärt wird.

Fonts sind in der Regel einfach konstante Arrays. Und eines oder mehrere 
davon, wählt man per define aus. Alle anderen ignoriert der Compiler und 
das kostet minimal Zeit. Es mag ja sein, dass Dein System ein wenig mehr 
Möglichkeiten bietet und deswegen flexibler bei der Fontauswahl sein 
muss, evtl. auch zur Laufzeit, je nach Font, unterschiedlich arbeiten 
muss; aber das solltest Du mal wirklich ausführlich, mit Grafiken 
(Daten- und Kontrollfluss) beschreiben und klarlegen, was Du erreichen 
willst, so das ein "Entwickler" das nachvollziehen kann ohne sich erst 
durch den Code zu wühlen und das reverse-engineeren muss.

von Daniel A. (daniel-a)


Angehängte Dateien:

Lesenswert?

Wie wär's mit weak symbols?
Ein lauffähiges Minimalbeispiel ist im Anhang.

Compilieren:
1
abd@basalt ~/tmp/g $ make clean all && ./bin/main
2
rm -rf "bin/main" "tmp"
3
mkdir -p "tmp"
4
gcc -c -std=c11 -Wall -Wextra -pedantic -Werror -I "src"/h/ "src/c/main.c" -o "tmp/main.o"
5
mkdir -p "tmp/font"
6
gcc -c -std=c11 -Wall -Wextra -pedantic -Werror -I "src"/h/ "src/c/font/characters_5x5.c" -o "tmp/font/characters_5x5.o"
7
gcc tmp/main.o tmp/font/characters_5x5.o -o "bin/main"
8
characters_5x5
9
10
abd@basalt ~/tmp/g $ make FONT="5x5 5x7" clean all && ./bin/main
11
rm -rf "bin/main" "tmp"
12
mkdir -p "tmp"
13
gcc -c -std=c11 -Wall -Wextra -pedantic -Werror -I "src"/h/ "src/c/main.c" -o "tmp/main.o"
14
mkdir -p "tmp/font"
15
gcc -c -std=c11 -Wall -Wextra -pedantic -Werror -I "src"/h/ "src/c/font/characters_5x5.c" -o "tmp/font/characters_5x5.o"
16
mkdir -p "tmp/font"
17
gcc -c -std=c11 -Wall -Wextra -pedantic -Werror -I "src"/h/ "src/c/font/characters_5x7.c" -o "tmp/font/characters_5x7.o"
18
gcc tmp/main.o tmp/font/characters_5x5.o tmp/font/characters_5x7.o -o "bin/main"
19
characters_5x5
20
characters_5x7

Main:
1
#include <stdio.h>
2
#include <font/font.h>
3
4
int main(){
5
  if(characters_5x5)
6
    printf("characters_5x5\n");
7
  if(characters_5x7)
8
    printf("characters_5x7\n");
9
}

: Bearbeitet durch User
von Malte _. (malte) Benutzerseite


Lesenswert?

Die Idee mit dem Weak gefällt mir. Danke :)

von Dr. Sommer (Gast)


Lesenswert?

Malte _. schrieb:
> Die Idee mit dem Weak gefällt mir. Danke :)

Das ist ja furchtbar... Braucht man wirklich eine 
Compiler/Linker-spezifische unportable Anweisung, um ein derart simples 
Problem zu lösen? Da sind die ersten Vorschläge doch wesentlich 
sauberer.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.