Results 1 to 3 of 3

Thread: A Makefile Tutorial

  1. #1

    Post A Makefile Tutorial

    A Makefile Tutorial By: volcanic

    (Could be part 1 of 2 if requested, see end of file)

    :::PREFACE:::
    Ive been learning C++ for the last few months, programming in linux and
    using the g++ compiler. I have used makefiles during the course of my learning but
    found them a bit hard to understand at first.
    I turned to AO for some good explinations,
    but couldn't come up with much of anything. Seeing that many people turn to AO to get help
    with learning C++, I thought I would pass what I learned on to others in the same boat as I am in.

    This Tutorial is specific only to C++ programming, I am not too sure about makefile equivalents in other
    languages, I am sure the equivalents are quite simmilar, but I don't want to misinform anyone.
    The basic premise of a makefile will allow it to be used for purposes other than compiling a program,
    but I will leave these purposes for another conversation.
    I do, however, welcome any comments that might be of use to somebody reading this tutorial.

    If anything stated below is inconsistent or incorrect, please reply or email me and I will edit my tutorial.
    Thank You!

    :::BASICS:::
    What is a makefile?
    At its most basic form, a makefile is a set of instructions
    that the compiler reads to turn your code into an executable file.
    Most programs that you write will contain more than one source
    code files (.cpp .h), so the makefile also acts as a set of instructions
    for your compiler to properly build the program out of these many
    source code files, this is called linking.

    How do I implement a makefile?
    By using the make utility(part of the *nix and/or shell command line).
    A good idea when writing the source for your program is to keep each
    program in it's own individual directory (seems logical enough). Then, in
    that particular directory, you will create your makefile (described below).
    Once you are ready to compile(make) your program, you type: make.
    Make will look for the makefile and take it from there.

    :::A QUICK NOTE:::
    -Comments can be placed in a Makefile by placing a pound s ign in front of the line
    to be commented (#).


    :::WALKTHROUGH:::
    ** Using the basic knowledge listed above, you should be armed with enough info
    COLOR=royalblue]**[/COLOR]to get you through the rest of this tutorial. Any additional comments/remarks are
    COLOR=royalblue]**[/COLOR]welcome.

    1. Simple Compilation:
    A small program requires at least one file. When a program is
    compiled, it goes through 3 stages:
    Compiler: All code is converted into assembly code (.s file).
    Assembler: Assembly code is converted into object code,
    making the origional code into a .o code (o for object).
    Linker: This stage links .o code with other .o code files used in your
    program.

    2. Multiple File Compilation:
    Source code that is divided up into more than one file goes through the same
    process as the simple compilation above, with just a few more rules.

    An example of a multiple file compilation:
    You have two .cpp (or .c) files that depend on the same .h file.
    The first stage (compiler) will convert each dependent pair into
    a .s file. So the first .cpp file will be assembled together with the .h
    file, creating a .s file. And the same happens with the other .cpp file.
    This leaves you with two .s files.
    The second stage (assembler) converts both of these .s files into .o
    files. Now you have two object files.
    The final stage links these two object files into one executable program,
    also called a run time image.

    3. Dependency:
    You can see from step 2 above that the final executable program was dependent
    on the two .o files made from the previous stage. You can also see that the two .o
    files were dependent on the 2 .cpp(or .c) and the one .h file. This concept is strangely
    enough called "dependency" and is one of the fundamental ideas behind the makefile.

    When calling the make command, make will check to see what needs to be done when,
    and in what order. For this, it uses each files timestamp. A timestamp is a record of the
    last time a file was modified.

    If you have the same program that we compiled and made into an executable above,
    and you go back and change something in one of the files, then your program will need
    to be re-compiled.

    Of course, you only changed one of the two .cpp (or .c) files, so make will compare the timestamps
    of each dependent file and will only re-compile those files who's timestamps are for a later time than
    their dependent's.

    4. Cleaning:
    Once you run make, provided your program compiles properly, you will have some new files
    appear in your directory; namely, the .o files and executable program you created.

    In order to go back and make a change to your source and change the executable program, you will
    need to run make again, but, make won't think it has anything to do if the .o files and the executable
    file it needs to create are sitting right there in the directory.
    So the files will need to be removed.
    You can do this in two ways.
    1. Remove them manually (using the rm filename command).
    2. Create something in your make file that will remove them for you.
    This "cleaner" will be shown in code a little later in the tutorial.

    :::THATS GREAT AND ALL
    BUT LET ME SEE SOME CODE:::
    ***Important Format*** The dependency code explained below follows this format:
    target: source files(s)
    ^^^^^^command(s)
    ^^^^^^Replace ^'s with 1 tab character. This MUST be a tab character, no exeptions.

    ***Compiler Note*** For the compiler commands below, I will use the command g++
    This can be replaced with the compier of your choice.

    *** Using the -c option in your compile command will cause only an object (.o) file to be
    produced. The last stage (linker) will not take place.

    *** When #including a .h file into a program, the .h file need not be in the makefile.
    But note, when the .h file changes, the rest of the program will not automatically be remade.

    1. Hierarchy
    When creating the code for your makefile, the format follows a hierarchial fashion,
    with the most important thing on top, the executable (run image)

    2. Lets Create An Example Program:
    I am going to explain this using the same program from #3 above,
    but let me use some names to make this easier.
    (2) .cpp files are called: me.cpp & you.cpp
    (1) .h file is called: him.h
    **Remember both me.cpp and you.cpp are dependent on him.h
    Our program is going to be called: projectUS.

    3. How to write this:
    First I will show the code, then I will explain it.

    Code:

    projectUS: me.o you.o
    g++ me.o you.o -o projectUS
    me.o: me.cpp him.h
    g++ -c me.cpp
    you.o: you.cpp him.h
    g++ -c you.cpp

    clean:
    rm *.o projectUS


    Explanation:

    The first line tells us that there will be a run image that will be called projectUS, and
    that it is dependent on me.o and you.o If the timestamps for the Rule Line (indented
    line two) are for a later time than those for the Dependent line (line one), then the
    commands for the Rule Line are followed. This rule line tells the dependent line how to
    get me.o and you .o. Notice that the g++ command is flagged with the -o flag, not the -c?
    This is because in this stage, the compiler will be linking objects, not compiling code into
    assembly language.

    So that second line will call both the third and fith lines to be run. Same thing here.
    me.o is dependent on me.cpp and him.h
    Timestamps are checked, and if needed, g++ -c me.cpp will be ran.
    Ditto for you.o

    Provided the code compiles with no errors, you will have an executable file in your directory.

    The clean line allows you to call the command: make clean
    This will run the command for clean listend in its rule line, namely removing all files in the directory
    that end witn *.o projectUS

    This brings up another good point. You can have one makefile that runs multiple programs.
    For the makefile above, you can either run: make clean, or make projectUS
    If you had another programs makefile in this file you could call: make otherProgramsName
    Where otherProgramsName, clean, and projectUS are called a makefiles target.



    :::LAST THOUGHTS/NOTES/REMINDERS:::
    -The make command will be able to find a makefile whether or not it is
    spelled with a capital M or a lowercase m. If you do not wish to use either
    of these, you can use the command: make -f whatevernameyouwant

    -In the case of having many files being made together, at least one of them must have
    a main() function.

    -No two functions can be named the same.

    -There are other nice little things that the make utility allows you to do, such as set macros
    and use pre-existing macros to make your makefiles easier to write and understand.
    If the audience would like, I can write a part 2 to this tutorial at a later date.


    Thank You For Reading

    Your Friend,
    Volcanic

  2. #2
    Senior Member
    Join Date
    Nov 2001
    Posts
    4,785
    as AO is supposed to be a place to gain and share knowledge a second tut of this quality would be deeply appreciated by all im sure.
    Bukhari:V3B48N826 “The Prophet said, ‘Isn’t the witness of a woman equal to half of that of a man?’ The women said, ‘Yes.’ He said, ‘This is because of the deficiency of a woman’s mind.’”

  3. #3
    Well, I will start working on a second as soon as possible. Im glad my first tutorial was accepted well by you all. I really hope it helps somebody out.

    Thanks to everybody that shares their knowledge!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •