#define per autotools generieren

Herakles

Profifragensteller
Moin!

Ich bin seit langem am Basteln, um ein Programm mit den autotools zum Laufen zu bringen. Um es zu vereinfachen, hab ich hier einfach mal ein hello world programm genommen.

Ich will erreichen, dass ein #define dem compiler mitgegeben wird, je nachdem, ob ich beim configure den Schalter "--enable-english" mitgebe oder eben nicht (oder einen beliebigen anderen, aber erstmal das als Beispiel).

Hier der code:

Code:
#include <stdio.h>

int main(int argc, char* argv[])
{
   printf("Hello, world!\n");

   return 0;
}

Dann habe ich die configure.ac angepasst:

Code:
AC_PREREQ([2.64])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE(hello, 1.0)
AC_CONFIG_FILES([Makefile])
(...)
AC_MSG_CHECKING(--enable-english argument)
AC_ARG_ENABLE(english,
        [  --enable-english     Use english language rather than german.],
        ENABLE_ENGLISH=$enableval,
        ENABLE_ENGLISH=yes)
if test x"${ENABLE_ENGLISH}" = xyes; then
        AC_DEFINE([ENGLISH], 1, [english language on display.])
else
        AC_DEFINE([GERMAN], 1, [german language on display.])
fi

Makefile.am sieht so aus:

Code:
bin_PROGRAMS=hello
hello_SOURCES=hello.c
AM_CFLAGS=-Wall

Jetzt folgen diese Befehle auf der Konsole:

Code:
:~/test$ autoheader
:~/test$ aclocal
:~/test$ automake
:~/test$ autoconf

Zu guter Letzt ein
Code:
./configure --enable-english

und meinem Verständnis zufolge sollte nun der Compiler mit einem define für ENGLISH kommen, also -DENGLISH. Passiert aber nicht:

Code:
test$ make
make  all-am
make[1]: Betrete Verzeichnis '~/test'
gcc -DHAVE_CONFIG_H -I.     -g -O2 -MT hello.o -MD -MP -MF .deps/hello.Tpo -c -o hello.o hello.c
mv -f .deps/hello.Tpo .deps/hello.Po
gcc  -g -O2   -o hello hello.o  
make[1]: Verlasse Verzeichnis '/~test'

Wo ist mein Fehler? Wieso ist nach dem configure-script kein -DENGLISH beim Compiler zu finden?

Danke für jeden Tipp,
Herakles
 
Ich vereinfache mal die configure.ac:

Code:
AC_PREREQ([2.64])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE(hello, 1.0)
AC_CONFIG_FILES([Makefile])
(...)
AC_DEFINE([ENGLISH], 1, [english language on display.])

Jetzt sollte eigentlich -DENGLISH beim compilen auftauchen - dem ist aber nicht so...

Hmmm... :confused:
 
So, Lösung gefunden. Manchmal muss man einfach nur eine Nacht drüber schlafen und schon geht's. Also:

Zu allererst fügt man seinem Sourcecode folgendes als allererstes include hinzu:

Code:
#include <config.h>

Wichtig ist danach noch, dass man nun dem Compiler mit auf den Weg gibt, dass er auch im entsprechenden Verzeichnis nach dieser config.h Datei suchen soll. In meinem Beispielfall ist das das aktuelle Verzeichnis, also "." :

Code:
AM_CFLAGS=-Wall -I.

Das "-Wall" hatte ich ja vorher schon drinne...

Nachdem ich damit nun meinen Quellcode erweitert habe, kann ich die autotools nochmal arbeiten lassen:

Code:
:~/test$ autoheader
:~/test$ aclocal
:~/test$ automake
:~/test$ autoconf

Das Ergebnis ist nun, dass innerhalb der Datei "./config.h" ein Define für "ENGLISH" vorhanden ist - wie eben in meinem Beispiel. Heißt: Die autotools scannen nun den Code und ads Makefile nochmal und passen dementsprechend die config.h an. Damit die config.h aber auch benutzt wird, muss sie natürlich #include-d werden. Das ist ja nunmehr geschehen.

Nach einem erneuten ./configure kann man dann im anschließenden Compilen immer noch kein "-DENGLISH" sehen - natürlich nicht! Denn: Das #define befindet sich ja nun in der config.h und muss daher nicht dem Compiler mitgegeben werden.

Also:
1. config.h in die Quellen als allererstes include mitgeben.
2. Makefile.am anpassen und "-I." hinzufügen zu den "AM_CFLAGS"
3. zu configure.ac AC_CONFIG_HEADERS([config.h]) direkt hinter dem AC_INIT hinzufügen und irgendwo darin ein AC_DEFINE([ENGLISH], [], [english language on display.]) reinhauen
4. autotools aufrufen
5. compilen
6. glücklich sein

Grüße,
Herakles
 
Kannst du nicht einfach #include "config.h" machen?

Der Mangel an Antworten entstammt meiner Meinung nach übrigens der weit verbreiteten Abneigung gegen die Autobreak Werkzeuge.
 
Dass ich kein #include "config.h" mache, habe ich von hier. In dem pdf heißt es:

The package should #include the configuration header file before any other header files, to prevent inconsistencies in declarations. Use #include <config.h> instead of #include ’config.h’, and pass the C compiler the -I option.

Eine Begrüdung wird nicht geliefert, weil mir das Dokument aber sonst sehr viel weitergeholfen hat und ich im Grunde eigentlich keine Ahnung davon habe, vertraue ich diesem Satz.

Was ist denn der Grund für die Abneigung? Wie macht man es denn anstelle dessen "elegant"?

Grüße
Herakles
 
Der Grund ist wahrscheinlich, dass #include "config.h" nur funktioniert, wenn die config.h im gleichen Verzeichnis liegt. Wenn du dann z.B. irgendwo in einem Unterverzeichnis bist, müsstest du wahrscheinlich ein #include "../config.h" verwenden.

Ich denke es geht also lediglich um Ästhetik und Copy'n'Paste Vereinfachung. Technisch hat keiner der Ansätze Vorteile.

Ich sehe das aber in der Regel so, dass ich Includes, die zum Projekt gehören mit "" mache und <> ist externen Bibliotheken vorbehalten.
 
autofuck

Was ist denn der Grund für die Abneigung?

Weil es nicht funktioniert. Weil es konzeptionell nicht funktionieren kann. Weil es unendlich viel Arbeit macht, kaputte autofuck-Magie zu reparieren (einfach mal in den Portstress von FreeBSD und OpenBSD bzw. in pkgsrc nach autofuck-Patches und Workarounds suchen). Weil es einen in den Wahnsinn treibt, wenn man in den genrierten Scripts bzw. (bei automake) Makefiles nach Bugs suchen muss. Und weil es langsam ist (seit der Umstellung auf autofuck dauert z.B. ein X11-Build unter OpenBSD gefuehlt 50 -- 100 % laenger).

Wie macht man es denn anstelle dessen "elegant"?

Durch einen Kommentar im Makefile, z.B.
Code:
# Uncomment to get english messages:
# CFLAGS += -DENGLISH
 
Was ist denn der Grund für die Abneigung? Wie macht man es denn anstelle dessen "elegant"?
Die Frage hatte ich übersehen.

In meinem Fall, dass Autobreak Dinge errät, die das Buildsystem (bei FreeBSD die Ports) zuverlässig mitteilen kann. Ein gutes Beispiel, warum das ein Problem ist, sind die kdelibs3. Die lassen sich nicht bauen, wenn openssl-1.0 installiert ist (was sich kaum vermeiden lässt). Es müsste einfach nur das openssl aus dem Basissystem verwenden, aber ich konnte es nie davon überzeugen das zu tun, ohne openssl-1.0 zu löschen.

Ein weiteres Problem sind optionale Features, die von Bibliotheken abhängen. Mit Autobreak werden dann alle Features aktiviert, für die die Bibliotheken vorhanden sind, statt die die man eigentlich will.
Im Extremfall ist das Programm dann gegen eine Bibliothek gelingt, ohne dass das Paketsystem etwas davon weiß. Entsprechend könnte die Bibliothek später deinstalliert werden und das Programm läuft ohne ersichtlichen Grund nicht mehr.

Solche Fehler sind natürlich leicht zu erkennen, wenn sie auftreten, aber wenn das mit einer kritischen Anwendung passiert kann es trotzdem sehr unangenehm sein. Besonders, wenn man die Anwendung gerade jetzt braucht.

Durch einen Kommentar im Makefile, z.B.
Code:
# Uncomment to get english messages:
# CFLAGS += -DENGLISH
Man kann auch ein Makefile.include anbieten in dem solche Einträge gemacht werden können, ohne das Projekt-Makefile anzufassen.
 
Der Grund ist wahrscheinlich, dass #include "config.h" nur funktioniert, wenn die config.h im gleichen Verzeichnis liegt. Wenn du dann z.B. irgendwo in einem Unterverzeichnis bist, müsstest du wahrscheinlich ein #include "../config.h" verwenden.

Jein. Ein include via
Code:
#include "file.h"
wird zeitlich spaeter als
Code:
#include <file.h>
vom Compiler behandelt. Deswegen sollten Systemheader immer via <> eingebunden werden, da diese als erstes gesucht werden.

Ansonsten ist natuerlich die Liste der Include Verzeichnisse (Option -I) entscheidend, um eine Datei zu finden. Die zuerst gefundene Datei wird eingebunden.

Ich verwende inzwischen ganz gerne CMake.

Es ist nicht so kaputt wie die Autotools, ist Cross Platform, laeuft u.a. unter Windows und die Dokumentation ist um einiges besser. Die Syntax ist zwar gewoehnungsbeduerftig und moeglicherweise findet CMake auch nicht alle lokalen Bibliotheken, aber das tun die Autotools ja auch nicht immer. ;)

Ausserdem wird bei CMake immer out-of-tree gebaut, es werden die Build Ergebnisse also nicht wild im Source verteilt, was ich persoenlich sehr praktisch finde. Andernfalls committed man leicht Buildergebnisse -Objektfiles oder so-, und solche FIles will man ja nicht via Versionskontrolle verwalten.
 
Jein. Ein include via
Code:
#include "file.h"
wird zeitlich spaeter als
Code:
#include <file.h>
vom Compiler behandelt. Deswegen sollten Systemheader immer via <> eingebunden werden, da diese als erstes gesucht werden.

Das ist falsch. #include-Direktiven werden in der Reihenfolge abgearbeitet, in der sie angetroffen werden (ISO/IEC 9899:1999 (E) §5.1.1.2:4). "" und <> entscheiden nur darüber, wo die einzubindende Datei gesucht wird (ISO/IEC 9899:1999 (E) §6.10.2:2+3).
 
Zurück
Oben