Makefile: Problem beim compilieren von mehreren Quelldatein



  • Hallo an alle,
    Ich wollte letztens eine Makefile schreiben die mehrere Dateien linkt und compiliert. Da ich vor kurzem noch keine Ahnung von Makefiles unter Linux hatte, habe ich mich in Teile vom GNU manual make eingelesen. Kapitel 2 und 3 habe ich gelesen. http://www.gnu.org/software/make/manual/make.html#Simple-Makefile Da steht ein bischen was, wie man mehrer Quelldateien verwaltet.
    Wenn ich die 2 Header Dateien und die main.cpp in eine IDE (QT Creator) lade und dann mit -std=c++11 und -lncurses compiliere, gibt es keine Fehlermeldung und ich kann das Programm(space invaders mit ncurses) im Terminal ausführen.
    Mein Ordner in denen sich die Quelldatein befinden sieht wie folgt aus:

    jo@jo-desktop:~/Dokumente/ncurses_tutorial/my/space_invaders$ ls -la
    insgesamt 56
    drwxrwxr-x  2 jo jo  4096 Jan 25 18:16 .
    drwxrwxr-x 19 jo jo  4096 Dez 30 15:16 ..
    -rw-rw-r--  1 jo jo  4640 Jan  9 19:20 bullet.hpp
    -rw-rw-r--  1 jo jo  6996 Jan 24 23:44 enemy.hpp
    -rw-rw-r--  1 jo jo  1741 Jan 11 18:03 main.cpp
    -rw-rw-r--  1 jo jo   234 Jan 25 17:53 Makefile
    -rw-rw-r--  1 jo jo   134 Dez 30 15:16 space_invaders.pro
    -rw-rw-r--  1 jo jo 17919 Jan 25 02:28 space_invaders.pro.user
    jo@jo-desktop:~/Dokumente/ncurses_tutorial/my/space_invaders$
    

    Hier die includes der einzelnen Dateien:
    enemy.hpp

    #include <ncurses.h>
    #include <vector>
    #include <chrono>
    

    bullet.hpp

    #include <chrono>
    #include <ncurses.h>
    #include <enemy.hpp>
    #include <vector>
    

    main.cpp

    #include <ncurses.h>
    #include <iostream>
    #include <bullet.hpp>
    

    Meine Makefile sieht wie folgt aus:

    CC        = g++
    TARGET    = space_invaders
    LIBS      = -lncurses
    
    $(TARGET) : main.o
    	$(CC) -o $(TARGET) main.o $(LIBS) -std=c++11
    
    main.o : main.cpp enemy.hpp bullet.hpp
    	$(CC) -c main.cpp $(LIBS) -std=c++11
    
    clean :
    	rm -f main.o
    

    Hier mal die Ausgabe der Makefile:

    jo@jo-desktop:~/Dokumente/ncurses_tutorial/my/space_invaders$ make
    g++ -c main.cpp -lncurses -std=c++11
    main.cpp:3:22: Schwerwiegender Fehler: bullet.hpp: Datei oder Verzeichnis nicht gefunden
    Kompilierung beendet.
    make: *** [main.o] Fehler 1
    jo@jo-desktop:~/Dokumente/ncurses_tutorial/my/space_invaders$
    

    Zur Vollständigkeit habe ich hier noch die Mafile die mir Qt Creator sozusagen generiert. Die eigentlichen Quelldateien befinden sich nicht im gleichen Ordner worin sich auch die Makefile befindet!
    Makefile

    #############################################################################
    # Makefile for building: space_invaders
    # Generated by qmake (3.0) (Qt 5.0.1) on: Sa. Jan. 25 18:33:03 2014
    # Project:  ../space_invaders/space_invaders.pro
    # Template: app
    # Command: /usr/lib/x86_64-linux-gnu/qt5/bin/qmake -spec linux-g++-64 CONFIG+=debug CONFIG+=declarative_debug CONFIG+=qml_debug LIBS+=-lncurses CONFIG+=c++11 -o Makefile ../space_invaders/space_invaders.pro
    #############################################################################
    
    MAKEFILE      = Makefile
    
    ####### Compiler, tools and options
    
    CC            = gcc
    CXX           = g++
    DEFINES       = -DQT_QML_DEBUG -DQT_DECLARATIVE_DEBUG
    CFLAGS        = -m64 -pipe -g -Wall -W -fPIE $(DEFINES)
    CXXFLAGS      = -m64 -pipe -g -std=c++0x -Wall -W -fPIE $(DEFINES)
    INCPATH       = -I/usr/share/qt5/mkspecs/linux-g++-64 -I../space_invaders -I.
    LINK          = g++
    LFLAGS        = -m64
    LIBS          = $(SUBLIBS) -lncurses 
    AR            = ar cqs
    RANLIB        = 
    QMAKE         = /usr/lib/x86_64-linux-gnu/qt5/bin/qmake
    TAR           = tar -cf
    COMPRESS      = gzip -9f
    COPY          = cp -f
    SED           = sed
    COPY_FILE     = cp -f
    COPY_DIR      = cp -f -R
    STRIP         = strip
    INSTALL_FILE  = install -m 644 -p
    INSTALL_DIR   = $(COPY_DIR)
    INSTALL_PROGRAM = install -m 755 -p
    DEL_FILE      = rm -f
    SYMLINK       = ln -f -s
    DEL_DIR       = rmdir
    MOVE          = mv -f
    CHK_DIR_EXISTS= test -d
    MKDIR         = mkdir -p
    
    ####### Output directory
    
    OBJECTS_DIR   = ./
    
    ####### Files
    
    SOURCES       = ../space_invaders/main.cpp 
    OBJECTS       = main.o
    DIST          = /usr/share/qt5/mkspecs/features/spec_pre.prf \
    		/usr/share/qt5/mkspecs/common/shell-unix.conf \
    		/usr/share/qt5/mkspecs/common/unix.conf \
    		/usr/share/qt5/mkspecs/common/linux.conf \
    		/usr/share/qt5/mkspecs/common/gcc-base.conf \
    		/usr/share/qt5/mkspecs/common/gcc-base-unix.conf \
    		/usr/share/qt5/mkspecs/common/g++-base.conf \
    		/usr/share/qt5/mkspecs/common/g++-unix.conf \
    		/usr/share/qt5/mkspecs/qconfig.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_bootstrap.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_concurrent.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_core.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_dbus.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_gui.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_network.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_opengl.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_platformsupport.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_printsupport.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_qml.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_qmldevtools.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_qmltest.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_quick.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_quickparticles.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_sql.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_testlib.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_widgets.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_xml.pri \
    		/usr/share/qt5/mkspecs/features/qt_functions.prf \
    		/usr/share/qt5/mkspecs/features/qt_config.prf \
    		/usr/share/qt5/mkspecs/linux-g++-64/qmake.conf \
    		/usr/share/qt5/mkspecs/features/spec_post.prf \
    		/usr/share/qt5/mkspecs/features/exclusive_builds.prf \
    		/usr/share/qt5/mkspecs/features/default_pre.prf \
    		/usr/share/qt5/mkspecs/features/unix/default_pre.prf \
    		/usr/share/qt5/mkspecs/features/debug.prf \
    		/usr/share/qt5/mkspecs/features/default_post.prf \
    		/usr/share/qt5/mkspecs/features/shared.prf \
    		/usr/share/qt5/mkspecs/features/c++11.prf \
    		/usr/share/qt5/mkspecs/features/qml_debug.prf \
    		/usr/share/qt5/mkspecs/features/declarative_debug.prf \
    		/usr/share/qt5/mkspecs/features/unix/gdb_dwarf_index.prf \
    		/usr/share/qt5/mkspecs/features/warn_on.prf \
    		/usr/share/qt5/mkspecs/features/wayland-scanner.prf \
    		/usr/share/qt5/mkspecs/features/testcase_targets.prf \
    		/usr/share/qt5/mkspecs/features/exceptions.prf \
    		/usr/share/qt5/mkspecs/features/yacc.prf \
    		/usr/share/qt5/mkspecs/features/lex.prf \
    		../space_invaders/space_invaders.pro \
    		../space_invaders/space_invaders.pro
    QMAKE_TARGET  = space_invaders
    DESTDIR       = 
    TARGET        = space_invaders
    
    first: all
    ####### Implicit rules
    
    .SUFFIXES: .o .c .cpp .cc .cxx .C
    
    .cpp.o:
    	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
    
    .cc.o:
    	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
    
    .cxx.o:
    	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
    
    .C.o:
    	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
    
    .c.o:
    	$(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
    
    ####### Build rules
    
    all: Makefile $(TARGET)
    
    $(TARGET):  $(OBJECTS)  
    	$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
    	{ test -n "$(DESTDIR)" && DESTDIR="$(DESTDIR)" || DESTDIR=.; } && test $$(gdb --version | sed -e 's,[^0-9]\+\([0-9]\)\.\([0-9]\).*,\1\2,;q') -gt 72 && gdb --nx --batch --quiet -ex 'set confirm off' -ex "save gdb-index $$DESTDIR" -ex quit '$(TARGET)' && test -f $(TARGET).gdb-index && objcopy --add-section '.gdb_index=$(TARGET).gdb-index' --set-section-flags '.gdb_index=readonly' '$(TARGET)' '$(TARGET)' && rm -f $(TARGET).gdb-index || true
    
    Makefile: ../space_invaders/space_invaders.pro /usr/share/qt5/mkspecs/linux-g++-64/qmake.conf /usr/share/qt5/mkspecs/features/spec_pre.prf \
    		/usr/share/qt5/mkspecs/common/shell-unix.conf \
    		/usr/share/qt5/mkspecs/common/unix.conf \
    		/usr/share/qt5/mkspecs/common/linux.conf \
    		/usr/share/qt5/mkspecs/common/gcc-base.conf \
    		/usr/share/qt5/mkspecs/common/gcc-base-unix.conf \
    		/usr/share/qt5/mkspecs/common/g++-base.conf \
    		/usr/share/qt5/mkspecs/common/g++-unix.conf \
    		/usr/share/qt5/mkspecs/qconfig.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_bootstrap.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_concurrent.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_core.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_dbus.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_gui.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_network.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_opengl.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_platformsupport.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_printsupport.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_qml.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_qmldevtools.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_qmltest.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_quick.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_quickparticles.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_sql.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_testlib.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_widgets.pri \
    		/usr/share/qt5/mkspecs/modules/qt_lib_xml.pri \
    		/usr/share/qt5/mkspecs/features/qt_functions.prf \
    		/usr/share/qt5/mkspecs/features/qt_config.prf \
    		/usr/share/qt5/mkspecs/linux-g++-64/qmake.conf \
    		/usr/share/qt5/mkspecs/features/spec_post.prf \
    		/usr/share/qt5/mkspecs/features/exclusive_builds.prf \
    		/usr/share/qt5/mkspecs/features/default_pre.prf \
    		/usr/share/qt5/mkspecs/features/unix/default_pre.prf \
    		/usr/share/qt5/mkspecs/features/debug.prf \
    		/usr/share/qt5/mkspecs/features/default_post.prf \
    		/usr/share/qt5/mkspecs/features/shared.prf \
    		/usr/share/qt5/mkspecs/features/c++11.prf \
    		/usr/share/qt5/mkspecs/features/qml_debug.prf \
    		/usr/share/qt5/mkspecs/features/declarative_debug.prf \
    		/usr/share/qt5/mkspecs/features/unix/gdb_dwarf_index.prf \
    		/usr/share/qt5/mkspecs/features/warn_on.prf \
    		/usr/share/qt5/mkspecs/features/wayland-scanner.prf \
    		/usr/share/qt5/mkspecs/features/testcase_targets.prf \
    		/usr/share/qt5/mkspecs/features/exceptions.prf \
    		/usr/share/qt5/mkspecs/features/yacc.prf \
    		/usr/share/qt5/mkspecs/features/lex.prf \
    		../space_invaders/space_invaders.pro
    	$(QMAKE) -spec linux-g++-64 CONFIG+=debug CONFIG+=declarative_debug CONFIG+=qml_debug LIBS+=-lncurses CONFIG+=c++11 -o Makefile ../space_invaders/space_invaders.pro
    /usr/share/qt5/mkspecs/features/spec_pre.prf:
    /usr/share/qt5/mkspecs/common/shell-unix.conf:
    /usr/share/qt5/mkspecs/common/unix.conf:
    /usr/share/qt5/mkspecs/common/linux.conf:
    /usr/share/qt5/mkspecs/common/gcc-base.conf:
    /usr/share/qt5/mkspecs/common/gcc-base-unix.conf:
    /usr/share/qt5/mkspecs/common/g++-base.conf:
    /usr/share/qt5/mkspecs/common/g++-unix.conf:
    /usr/share/qt5/mkspecs/qconfig.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_bootstrap.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_concurrent.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_core.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_dbus.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_gui.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_network.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_opengl.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_platformsupport.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_printsupport.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_qml.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_qmldevtools.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_qmltest.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_quick.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_quickparticles.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_sql.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_testlib.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_widgets.pri:
    /usr/share/qt5/mkspecs/modules/qt_lib_xml.pri:
    /usr/share/qt5/mkspecs/features/qt_functions.prf:
    /usr/share/qt5/mkspecs/features/qt_config.prf:
    /usr/share/qt5/mkspecs/linux-g++-64/qmake.conf:
    /usr/share/qt5/mkspecs/features/spec_post.prf:
    /usr/share/qt5/mkspecs/features/exclusive_builds.prf:
    /usr/share/qt5/mkspecs/features/default_pre.prf:
    /usr/share/qt5/mkspecs/features/unix/default_pre.prf:
    /usr/share/qt5/mkspecs/features/debug.prf:
    /usr/share/qt5/mkspecs/features/default_post.prf:
    /usr/share/qt5/mkspecs/features/shared.prf:
    /usr/share/qt5/mkspecs/features/c++11.prf:
    /usr/share/qt5/mkspecs/features/qml_debug.prf:
    /usr/share/qt5/mkspecs/features/declarative_debug.prf:
    /usr/share/qt5/mkspecs/features/unix/gdb_dwarf_index.prf:
    /usr/share/qt5/mkspecs/features/warn_on.prf:
    /usr/share/qt5/mkspecs/features/wayland-scanner.prf:
    /usr/share/qt5/mkspecs/features/testcase_targets.prf:
    /usr/share/qt5/mkspecs/features/exceptions.prf:
    /usr/share/qt5/mkspecs/features/yacc.prf:
    /usr/share/qt5/mkspecs/features/lex.prf:
    ../space_invaders/space_invaders.pro:
    qmake: FORCE
    	@$(QMAKE) -spec linux-g++-64 CONFIG+=debug CONFIG+=declarative_debug CONFIG+=qml_debug LIBS+=-lncurses CONFIG+=c++11 -o Makefile ../space_invaders/space_invaders.pro
    
    qmake_all: FORCE
    
    dist: 
    	@test -d .tmp/space_invaders1.0.0 || $(MKDIR) .tmp/space_invaders1.0.0 
    	$(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/space_invaders1.0.0/ && (cd `dirname .tmp/space_invaders1.0.0` && $(TAR) space_invaders1.0.0.tar space_invaders1.0.0 && $(COMPRESS) space_invaders1.0.0.tar) && $(MOVE) `dirname .tmp/space_invaders1.0.0`/space_invaders1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/space_invaders1.0.0
    
    clean:compiler_clean 
    	-$(DEL_FILE) $(OBJECTS)
    	-$(DEL_FILE) *~ core *.core
    
    ####### Sub-libraries
    
    distclean: clean
    	-$(DEL_FILE) $(TARGET) 
    	-$(DEL_FILE) Makefile
    
    check: first
    
    compiler_wayland-server-header_make_all:
    compiler_wayland-server-header_clean:
    compiler_wayland-client-header_make_all:
    compiler_wayland-client-header_clean:
    compiler_wayland-code_make_all:
    compiler_wayland-code_clean:
    compiler_yacc_decl_make_all:
    compiler_yacc_decl_clean:
    compiler_yacc_impl_make_all:
    compiler_yacc_impl_clean:
    compiler_lex_make_all:
    compiler_lex_clean:
    compiler_clean: 
    
    ####### Compile
    
    main.o: ../space_invaders/main.cpp ../space_invaders/bullet.hpp \
    		../space_invaders/enemy.hpp
    	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o main.o ../space_invaders/main.cpp
    
    ####### Install
    
    install:   FORCE
    
    uninstall:   FORCE
    
    FORCE:
    

    Wenn ich diese Makefile "ausführe" wird das Programm erfolgreich compiliert.
    Was ist also an meiner selbstgeschriebenen Makefile falsch?



  • Das Problem ist, dass du deine Headers mit

    #include <bullet.hpp>
    

    includest. Die eckigen Klammern bedeuten, dass der Compiler in den Standardpfaden nach der Datei sucht (/usr/include und so).

    Er such aber standardmässig nicht im aktuellen Verzeichnis.

    Jetzt gibt es zwei Möglichkeiten:

    1. Du änderst die Zeile (und das andere Include mit enemy.hpp) zu

    #include "bullet.hpp"
    

    oder du sagst dem Compiler, er soll auch im aktuellen Verzeichnis nach den Dateien suchen, und das macht man mit der Option " -I. " (Erklärung: -I<pfad> fügt <pfad> zur Liste hinzu und das aktuelle Verzeichnis ist unter Linux ".", deshalb -I.).

    Der normale Weg wäre dies über CFLAGS zu tun:

    CC        = g++
    CFLAGS    = -I. -std=c++11
    TARGET    = space_invaders
    LIBS      = -lncurses
    
    $(TARGET) : main.o
        $(CC) $(CFLAGS) -o $(TARGET) main.o $(LIBS)
    
    main.o : main.cpp enemy.hpp bullet.hpp
        $(CC) $(CFLAGS) -c main.cpp $(LIBS)
    
    clean :
        rm -f main.o
    

    (ich habe auch gleich -std=c++11 zu CFLAGS hinzugefügt).

    Über CFLAGS kannst du später auch Optimierungen anschalten, mit -O3.



  • Ich Danke Dir für deine extreme schnelle und gute Antwort :). Ich kann das Programm nun compilieren. 😉


Anmelden zum Antworten