PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Grundlegende Makefile-Frage


samm
2010-03-24, 22:37:28
Hallo zusammen,

Nachdem ich mir nun Tutorials durchgelesen habe etc. steh ich immer noch auf dem Schlauch: Ich arbeite an einem C++-Projekt auf Linux, und muss ein Makefile schreiben, was die Chose kompiliert. Nun habe ich eine Ordnerstruktur, die so aussehen soll:

-[Projekt]
Makefile
Readme
...
- -[src]
bla.cpp
...
- -[include]
- - -[libA]
libx.hpp
liby.hpp
...
- - -[libB]
bla.hpp
...
- -[build]
bla.o
KompiliertesExecutable

Also: Das Makefile liegt im Grundordner, dann gibt es diverse Unterordner. Meine Sourcefiles binden die benötigte library libx.hpp via
#include "../include/libA/libx.hpp"
ein, allerdings hängt die lipx.hpp wiederum mittels
#include <include/lib/liby.hpp>
von andern libraries im gleichen Ordner ab.

Wie gestalte ich nun das Makefile so, dass ich das ganze kompilieren kann, sodass die Dateien in ihren jeweiligen Unterordnern liegen bleiben können und das Kompilat im richtigen Unterordner landet? Die includes in meinen Source- und Header-Files kann ich abändern, die in den Library-Files nicht. Meine Source-Files kann ich auch verschieben (ausser in den [lib]-Ordner), und ob das Kompilat nun wirklich im [build]-Ordner landet, ist nicht dermassen wichtig. Die "Header-Files" von [libA] enthalten den Sourcecode der Library, kompilierte habe ich nicht. Die Header-Files von [libB] sind einfach die Header-Files zu meinen Source-Files.

Das einzige, was ich hinbringe, ist, den make-Prozess zu starten, wenn das Makefile auch im Ordner [src] liegt, dann motzt aber der compiler, weil er die includes innerhalb der library-Files nicht auflösen kann. Das Makefile enthält sowas (ja, es ist nicht gerade aufgeräumt, enthält ungentutze Variabeln von fehlgeschlagenen Versuchen etc....)

SRCDIRS = src
INCDIRS = $(SRCDIRS) include/libA include/libB /usr/include/c++/4.4.1
CPP = g++
CFLAGS = $(INCDIRS) -O0
DBG = -g3
LFLAGS =
LIBDIRS = $(INCDIRS)
LIBS =
OBJS = bla.o
EXECUTABLE = MyExec

all: ${EXECUTABLE}

program: ${EXECUTABLE}

run: program
./${EXECUTABLE}

${EXECUTABLE}: ${OBJS}
$(CPP) $(LFLAGS) $(DBG) $(OBJS) $(LIBDIRS) $(LIBS) -o $@

%.o : %.cpp %.h
$(CPP) $(CFLAGS) $(DBG) -c $< -o $@

clean:
- rm *.o *~
- rm ${EXECUTABLE}

depend: *.h *.cpp
- rm depend
$(CPP) $(CFLAGS) $(DBG) -MM *.cpp > depend

include depend

Ihr müsst mir jetzt nicht das Makefile schreiben (ausser ihr wollt ;)), aber um Antworten, wie ich die verschiedenen Unterordner handhaben kann, darüber wäre ich sehr dankbar!

Daedalus
2010-03-24, 23:12:59
ist zwar etwas ot, aber guck dir mal premake (http://industriousone.com/premake) an. das nimmt dir viel an arbeit ab.

samm
2010-03-25, 00:02:17
Das hilft mir nicht weiter, da muss ich ne neue Skripting-Sprache lernen und auf den ersten Blick sehe ich zwar, wie ich einen build-Ordner angeben kann, nicht aber, wie ich das premake-file, die source-files und die library-files in der angegebenen Ordnerstruktur organisieren kann. Stünde wieder vor dem gleichen Problem, nur in ner andern Skript-Umgebung. Danke trotzdem ;)

Anyone else?

Gnafoo
2010-03-25, 00:46:42
Ich kenne mich mit Makefiles auch nur sehr begrenzt aus, aber sollte bei den include-Pfaden nicht ein -I davor stehen? Zumindest dürfte das beim GCC so sein und die Standard-Pfade sollte dieser auch selbst finden D. h.:


INCDIRS = -Isrc -Iinclude/libA -Iinclude/libB
...


Edit: und für die Libraries bräuchtest du -L[pfad], und entsprechende -l[name].
Sind die Libraries bereits kompiliert? Wenn ja, wo liegen die Binaries?

http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Directory-Options.html#Directory-Options

samm
2010-03-25, 07:08:17
Hm, das werd ich versuchen mit -L und -I... Bezüglich kompilierte Libs: Nein, die libraries liegen mir nur als header-files vor.

Gnafoo
2010-03-25, 13:29:41
Okay nochmal von vorne. Es gibt folgende Möglichkeiten:


Die Libraries sind Header-only (d. h. in den Headern steht auch der gesamte Quellcode), dann reicht es aus die Header-Files einzubinden.

Sie sind nicht Header-only und...

Du hast die Binaries. Dann ist die Frage, ob im Systemverzeichnis, oder irgendwo in deiner Ordnerstruktur.
Du hast den vollständigen Quellcode. Dann musst du die Binaries selbst kompilieren und einbinden.
Du hast weder Quellcode, noch Binaries. Dann kannst du dein Programm nicht linken.

samm
2010-03-25, 16:50:07
Fall 1. trifft zu. Sie sind header-only. In meinem Beispiel enthalten die *.hpp-Files in [libA] tatsächlich allen Sourcecode (wasn das für ein Stil?), die *.hpp-Files in [libB] sind die header-Files für die *.cpp-Files in [src]. Habe mein Eingangs-Posting angepasst.

Wenn du sagst, es reicht, die header-Files einzubinden: Das ist ja schön und gut, aber wie mache ich das im Makefile xD

Coda
2010-03-25, 18:05:17
Indem du INCDIRS entsprechend abänderst natürlich.

Gnafoo
2010-03-25, 18:09:22
Indem man GCC per -I... mitteilt, wo die Header zu finden sind (Edit: Coda hat es schon gesagt: über INCDIRS=-I...). Das sollte dann eigentlich ausreichen. Dein Problem hier ist vermutlich eher, dass make die Quellcodedatei zur bla.o im src-Verzeichnis nicht findet (welcher Fehler kommt denn im Moment?). Da bin ich mit meinen Make-Kenntnissen aber auch eher überfragt.

Vielleicht kommst du damit weiter:
http://www.gnu.org/software/make/manual/html_node/Directory-Search.html#Directory-Search

Gast_samm
2010-03-25, 23:07:34
Danke für den Link Gnafoo!

Die INCDIRS-Variable hatte ich schon angepasst, ja, auch unter Benutzung von -I.

Habe momentan keinen Zugriff drauf, aber afair hatte die Fehlermeldung etwas damit zu tun, dass im File libx.hpp die Direktive
#include <libA/liby.hpp>
nicht befolgt werden konnte, à la "Datei libA/liby.hpp nicht gefunden".

Werde mich später wieder melden, da in der Zwischenzeit die Library geändert wurde und deswegen ein massives refactoring im Gange ist... Evt. löst sich das Problem ja von selbst, weil z.B. die includes in der library nicht mehr so stehen *hoff*

MadMan2k
2010-03-26, 18:09:53
also wer für neue Projekte immer noch make benutzt ist selbst schuld. Scons ist viel besser dokumentiert und man muss keine unnötige scriptsprache lernen:
http://www.scons.org/doc/1.3.0/HTML/scons-user/x3894.html

Gast
2010-03-26, 20:56:56
also wer für neue Projekte immer noch make benutzt ist selbst schuld. Scons ist viel besser dokumentiert und man muss keine unnötige scriptsprache lernen:
http://www.scons.org/doc/1.3.0/HTML/scons-user/x3894.html
Och, ich finde um ein bisschen Verständnis zu erlangen ist Makefiles hacken ganz gut...

Ansonsten nimmt man halt cmake :)

Nasenbaer
2010-03-26, 22:27:33
Ansonsten nimmt man halt cmake :)

Ich kann auch nur CMake empfehlen. die CMake-Tools gibts auch für Windows womit man mit ein paar Klicks ein VisualStudio Projekt erstellen kann. Außerdem ist die Syntax IMO wesentlich leichter verständlich.

http://www.cmake.org/cmake/help/cmake_tutorial.html

samm
2010-04-08, 20:30:25
Tjo, dann mal Feedback:

Wie es aus euren Antworten mehr oder weniger rüberkam (auch wenn niemand ganz explizit sagte "ich kann das nicht" oder "das geht gar nicht" ;)), habe ich die Lösung nicht gefunden und benutze jetzt cmake.

Ectoplasma
2010-04-09, 08:37:26
Ich habe nicht die geringste Ahnung, wo überhaupt das Problem liegt. Es wäre schön, wenn du dich klarer ausdrücken würdest. Zudem wüsste ich nicht, was mit dem normalen gnu make nicht gehen sollte.

So werfe ich mal etwas Beispielcode hier ein, in der Hoffnung, dass dieser dein Problem löst, welches auch immer das ist.



BUILDDIR=<your object file an executable path>

...

%.o: %.cpp
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(BUILDDIR)/$@ -c $<

...

SRCS=$(SOURCE_FILES) $(HEADER_FILES)

VPATH=$(BUILDDIR):<plus all other source pathes> :...:

OBJS=$(notdir $(patsubst %.cpp,%.o,$(filter %.cpp,$(SRCS))))
OBJSDIR=$(patsubst %,$(BUILDDIR)/%,$(OBJS))


$(EXECUTABLE): $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJSDIR) $(LIBS)

...



Google mal bitte nach VPATH.