Makefiles and such

Nil_IQNil_IQ Join Date: 2003-04-15 Member: 15520Members
<div class="IPBDescription">How I do Lunix?</div>So i'm not a big fan of Linux. Mostly because i've never really used it much, and also because i'm terminally lazy and Linux generally makes me work harder than Windows. So imagine my delight when I find that my 3rd year project has to be done under Linux rather than under windows as I had originally assumed. Thankfully I have a fairly Linux-savvy friend to help me out when things get too Linuxy, but i've stumbled across a problem that even he is unable to help me with.

Essentially what I need to do is take the output of an existing program (written by someone else from the interweb, but with full permission to do so) and send it to another program (written by someone from within the University). In this case this has meant modifying both programs to use sockets. I can do the actual programming required to make the program use sockets.... I just don't know what i'm supposed to do to the makefile to make it compile properly. There are actually two files in the directory, makefile and makefile.in, and i'm not sure what the difference is. The only difference I can see is the section towards the top, which is slightly different in makefile.in. I've posted first the whole of makefile, and then just the section of makefile.in which differs.

<!--quoteo--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--quotec-->### RtMidi tests Makefile - for various flavors of unix

PROGRAMS = midiinfo midiout qmidiin cmidiin sysextest
RM = /bin/rm
SRC_PATH = ../
INCLUDE = ../
OBJECT_PATH = Release
vpath %.o $(OBJECT_PATH)

OBJECTS = RtMidi.o

CC = g++
DEFS =
DEFS += -D__LINUX_ALSASEQ__
CFLAGS = -O2
CFLAGS += -Wall -I$(INCLUDE)
LIBRARY = -lpthread -lasound
LIBRARY +=

%.o : $(SRC_PATH)/%.cpp
$(CC) $(CFLAGS) $(DEFS) -c $(<) -o $(OBJECT_PATH)/$@

all : $(PROGRAMS)

midiinfo : midiinfo.cpp $(OBJECTS)
$(CC) $(CFLAGS) $(DEFS) -o midiinfo midiinfo.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)

midiout : midiout.cpp $(OBJECTS)
$(CC) $(CFLAGS) $(DEFS) -o midiout midiout.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)

qmidiin : qmidiin.cpp $(OBJECTS)
$(CC) $(CFLAGS) $(DEFS) -o qmidiin qmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)

cmidiin : cmidiin.cpp $(OBJECTS)
$(CC) $(CFLAGS) $(DEFS) -o cmidiin cmidiin.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)

sysextest : sysextest.cpp $(OBJECTS)
$(CC) $(CFLAGS) $(DEFS) -o sysextest sysextest.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)


clean :
-rm $(OBJECT_PATH)/*.o
-rm $(PROGRAMS)
-rm -f *~

strip :
strip $(PROGRAMS)<!--QuoteEnd--></div><!--QuoteEEnd-->

And the "different" part in makefile.in:

<!--quoteo--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--quotec-->CC = @CXX@
DEFS = @debug@
DEFS += @midi_api@
CFLAGS = @cflags@
CFLAGS += @warn@ -I$(INCLUDE)
LIBRARY = @LIBS@
LIBRARY += @frameworks@<!--QuoteEnd--></div><!--QuoteEEnd-->


I'd hoped it would be as simple as adding the lines

<!--quoteo--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--quotec-->Socket : Socket.cpp $(OBJECTS)
$(CC) $(CFLAGS) $(DEFS) -o Socket Socket.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)

ClientSocket : ClientSocket.cpp $(OBJECTS)
$(CC) $(CFLAGS) $(DEFS) -o ClientSocket ClientSocket.cpp $(OBJECT_PATH)/RtMidi.o $(LIBRARY)
<!--QuoteEnd--></div><!--QuoteEEnd-->

to the either or both of the makefiles, as Socket.cpp and ClientSocket.cpp are the only source files I want to add (there are some headers also, but I was under the impression that those handle themselves; I can't see any listed in the makefile for instance). Unfortunately, this is not the case. I have to do something probably far more complicated.

I've looked for a decent guide on makefileing, but most of them give me little clue what is going on here. If someone can explain just what these lines of near incomprehensible.... stuff.... mean, I would owe that someone many E-cookies. Those are still a valid form of currency here, right?

Comments

  • puzlpuzl The Old Firm Join Date: 2003-02-26 Member: 14029Retired Developer, NS1 Playtester, Forum Moderators, Constellation
    edited February 2007
    Makefile.in is used to make a makefile. It contains macros that get expanded based on the local system configuration.

    If you have a working Makefile, then just ignore Makefile.in.


    Assuming you have tab characters in front of the commands in your Socket and ClientSocket targets then they look okay. You will need to add the targets to the all: target or it won't get invoked unless you explicitly add it to the command line.

    The all target is the key.

    all : $(PROGRAMS)

    When you invoke 'make' with no arguments it will try to satisfy the first target's dependencies in the filec ( in this case, all ). $PROGRAMS does not contain your new targets, so therefore they will not be looked at. You need to edit

    PROGRAMS = midiinfo midiout qmidiin cmidiin sysextest

    to

    PROGRAMS = midiinfo midiout qmidiin cmidiin sysextest Socket ClientSocket

    Alternatively, you can simply invoke those targets with make

    bash-$ make Socket ClientSocket


    80% of the features you should ever need to know about make are really straight forward. The file you have is very basic, but also very badly written. It is more confusing than it needs to be, and contains redundant targets and rules.
  • Nil_IQNil_IQ Join Date: 2003-04-15 Member: 15520Members
    edited February 2007
    Thanks for the reply. Unfortunately it now gives me a variable number of compile errors based on the order in which I choose to compile files. <img src="style_emoticons/<#EMO_DIR#>/confused-fix.gif" style="vertical-align:middle" emoid="???" border="0" alt="confused-fix.gif" />


    When I add Socket and ClientSocket to the list of programs in the makefile, it DOES try to compile them... and promptly fails. I've also noticed that regardless of the order I tell the makefile to compile in, it ALWAYS starts with either ClientSocket or Socket, whichever is first in the list, which seems strange. Or is it only showing output from the file which causes it to fail? It certainly doesn't like having qmidiin (the main program) compiled before Socket or ClientSocket because it complains about undefined references. If I compile in the order midiinfo midiout Socket ClientSocket qmidiin cmidiin sysextest I get this in response:

    <!--quoteo--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--quotec-->rtmidi-1.0.6/tests> make
    g++ -O2 -Wall -I../ -D__LINUX_ALSASEQ__ -o Socket Socket.cpp Release/RtMidi.o -lpthread -lasound
    /usr/lib/gcc/i586-suse-linux/4.1.0/../../../crt1.o: In function `_start':
    init.c:(.text+0x18): undefined reference to `main'
    collect2: ld returned 1 exit status
    make: *** [Socket] Error 1
    <!--QuoteEnd--></div><!--QuoteEEnd-->

    If I do the same, but with ClientSocket first, I get many complaints about undefined references to functions in Socket, so that clearly won't work either. It seems to be looking for a main function in Socket, but Socket doesn't HAVE a main function. Is there a way to inform the makefile as such?

    The original makefile for the socket program, if it helps, goes something like this:

    <!--quoteo--><div class='quotetop'>QUOTE</div><div class='quotemain'><!--quotec-->

    simple_client_objects = ClientSocket.o Socket.o simple_client_main.o


    all : simple_client

    simple_client: $(simple_client_objects)
    g++ -o simple_client $(simple_client_objects)


    Socket: Socket.cpp
    ClientSocket: ClientSocket.cpp
    simple_client_main: simple_client_main.cpp


    clean:
    rm -f *.o simple_client<!--QuoteEnd--></div><!--QuoteEEnd-->

    I can't help but notice that it compiles all three files to seperate object files, wheras RtMidi uses just one. Is that part of the problem?

    *edit*

    To clarify, simple_client consists of JUST the socket code. What i'm trying to do is put this code into RtMidi so that I can recieve MIDI data, then pass it to another program.
  • puzlpuzl The Old Firm Join Date: 2003-02-26 Member: 14029Retired Developer, NS1 Playtester, Forum Moderators, Constellation
    So what you are really asking for is a tutorial on how to use make? The problem you have is very very trivial to solve and it appears to me that you are just using trial and error with dependency orders to solve the problem rather than trying to understand how make works.

    No offence, but you'll never learn anything useful that way. I really suggest you should RTFM on this one and learn the basics of how make works.

    However, if you really just want a makefile that works, just send me your existing makefile and I'll fix it up for you.
  • Nil_IQNil_IQ Join Date: 2003-04-15 Member: 15520Members
    edited February 2007
    Forgive me if i'm coming across as a noob. This is because I am, in fact, a noob. I compiled my first C++ program in Linux just three weeks ago, and this is proving to be something of a sharp learning curve.

    Although it would be nice to just have the solution handed to me, I would like to know what the makefile is trying to do now, why it isn't working, and how I can fix it. Myself. I can't RTFM if I don't know where the M is. I've read tutorials on how to create a makefile, and none of them looked even nearly as complicated as this. I can see what the makefile is doing, I just don't understand why it isn't working, and having things in the wrong dependancy order (or having some missing dependencies) is the only reason I can see it would be complaining about not being able to find something.

    I've already corrected my first mistake; Socket and ClientSocket don't need to be in the list of programs, because they don't actually produce an executable at the end. Now it just complains about qmidiin having undefined references. So I tried adding any files I can think of that qmidiin could possibly depend on to its dependancies.... nothing.

    What I really need to know is; how do I tell the makefile that qmidiin depends on Socket.h, Socket.cpp, ClientSocket.h and ClientSocket.cpp? As far as I understand it, it <i>should</i> just be a line like:

    qmidiin : qmidiin.cpp ClientSocket.cpp Socket.cpp ClientSocket.h Socket.h

    But that doesn't work.

    So if that's not how I tell the makefile that qmidiin depends on those files, how do I?
Sign In or Register to comment.