Tutorial 2: Makefiles, basics of C, compiling source code and dealing with errors

This second tutorial will cover makefiles, a very basic run down of the C programming language, compiling source code using the template examples found in DevKitPro and dealing with compiling errors. This tutorial came out way longer than I expected and I’m hoping to keep other tutorials shorter than this one. You can grab the PDF of this tutorial here: codemii-tutorial-2.

When you’re compiling source code, the program that does the compiling needs to know what to compile, which libraries to include, compiling options, optimisations, etc and this is what a makefile is used for.


Makefiles

A makefile is usually found that the root directory of the source code you have. Take the gamecube template source code example (C:\devkitPro\examples\gamecube\template). In that directory you will see a file name “Makefile”. If you open it up with notepad, you’ll be able to see the different parts of a makefile.

The important parts of a makefile for this tutorial are the following lines:

[sourcecode language=’c’]include $(DEVKITPPC)/gamecube_rules[/sourcecode]

By specificing “gamecube_rules” we are telling our compiler that the source code we want to compile will be run on the gamecube. You would use “wii_rules” to compile for the Wii.

By changing between these two, you are changing which libraries will be used when compiling the source code. Libraries are a bunch of files which we use in our source code to interact with the gamecube or Wii system.

[sourcecode language=’c’]SOURCES := source
DATA := data
INCLUDES := [/sourcecode]

These lines tell the compiler which files should be compiled. Most of the time you can leave this alone as our source code will be in /source and our additional files like images, music, etc will be in /data.

[sourcecode language=’c’]LIBS := -logc –lm[/sourcecode]

This is a very important line as it tells the compiler which additional libraries we wish to use. Say we want to play an mp3 and have the relevant code in our source to do so. If we were to compile our source with the above line, the compiler would complain and say that it can’t find the functions we are using to play an mp3 file. For playing mp3 files, you need to include the “lmad” library.

The LIBS line when we add the lmad library looks like:
[sourcecode language=’c’]LIBS := -lmad -logc –lm[/sourcecode]

The order of how you include your libraries is also important as some libraries may reference other libraries and if you haven’t got them in the right order, the compiler will complain about it.


Basics of C

So we’ve quickly covered the more important parts of makefiles, we are now ready to learn some basics of the C programming language (which is kind of similar to most other programming languages). If you wish to learn much more about C programming just check the net for in depth tutorials which will explain things much clearer than what I’m doing.

Firstly we will cover variables. A variable as the name suggests is a symbol that can change its value. In the example below we are assigning 0 to the variable test.

[sourcecode language=’c’]int test = 0;[/sourcecode]

The variable test is of type int which means integer (number). So we are assigning the number 0 to the variable test.

There are different types of variables in the C programming language which include:

  • boolean can either be true or false. E.g. bool test = false;
  • int / long is integer that can range from -2,147,483,648 to 2,147,483,648. E.g int test =5;
  • float is a precise decimal point number that can range from +/- 3.4e +/- 38 (~7 digits). E.g float test = 3.14159
  • double is another precise decimal point number from +/- 1.7e +/- 308 (~15 digits). E.g double test = 3.1415926535897
  • char is a single character or integer that represent a character. E.g. char test = ‘a’;

The next thing we’ll cover is control structures, some include if, else, while and for

[sourcecode language=’c’]int test = 5;
if (test == 5) { //do something }
else { //do something else }[/sourcecode]

The above code is a demonstration of an “if” statement. If the variable “test” is equal (==) to 5 then “//do something” will be run. If we had set the “test” variable to 4, then “// do something else” would be run. The double slashes (//) means that all the text after the slashes is a comment in the code.

The double equals signs (==) is what we call an operator. There are many operators, some include:
<= means less than or equal to
>= means more than or equal to
!= means not equal to

[sourcecode language=’c’]int test = 0;
while (test < 5) { printf(“ok”); test++ }[/sourcecode] The above code is a while loop, which continually checks to make sure that if “test” is less than 5 then it will print the text “ok” to the screen and then increment the “test” variable, which means it will add 1 to “test”. In an example run, “test” would start out at 0, it would print “ok” to the screen and then “test” would be “test” + 1. It would then go back to the while condition and test if “test” is less than 5 which in this case “test” would be equal to 1 and so it would print “ok”, etc. The for loop is similar to the while loop except that we will know before we enter the loop, how many times we will run the loop. [sourcecode language='c']int test; for (test = 0; test < 5; test++) { printf(“ok”); }[/sourcecode] Notice how the “test” variable hasn’t been declared and we are assign the integer in the for loop. The for loop has three arguments, the starting count (test = 0), the condition (test < 5) and what to do after each loop which is usually increment the starting variable (test++). This example for loop would print “ok”5 times. There is a data structure which is often used which is called an array. An array is a set of elements contained in a structure. [sourcecode language='c']int myarray[50]; myarray[0] = 1234;[/sourcecode] In the above code we are setting up an array of type int and setting 50 elements to be in that array. The next line shows us assigning the first element (yes, 0 is always the start of an array) of the array the value of 1234. In almost any source code that you will see, it will most likely contain an array of some sort, so it’s best that you learn about arrays. Functions are useful if need to do something repetitive, for example, if your program were to print a list of numbers in an array on the screen you wouldn’t want to individually print each element of the array by writing the code, but rather use a function which could print all the elements of that array for you. [sourcecode language='c']void myfunction () { printf(“hi”); }[/sourcecode] In the above code, we have the function name “myfunction” which prints out “hi” to the screen. All functions need to return something once they have finished except if they have void before the function name. Void just means that this function will not return anything. We can call our function “myfunction” by using: myfunction(); If we want to have a function return a certain value, be it an int, float, bool, etc, we can stick these types just before the function name as shown below. [sourcecode language='c']int myfunction (int number) { printf(“%i”, number); return number; }[/sourcecode] What we are doing in the above function is we will be printing and returning the integer we receive in our function argument. So if we called int test = myfunction(5); it would print 5 to the screen and return 5 to the variable “test”. Now the %i part of printf means that we will be replacing %i with an integer, in this case the integer is the taken from the “number” variable. We can use %f for printing out a float, %l for a long, etc.
Reading the source code

So that’s the basics of the C programming language which should get us through this tutorial. We are now ready to compile our first source code. We will be using the Wii template file instead of the Gamecube one as it’s actually got comments in the source which will help us to learn more.

Navigate to C:\devkitPro\examples\Wii\template and open up the template.pnproj file which should open up with Programmer’s Notepad. When loaded, on the left hand side you will see the directory structure. Open up the template.c file by double clicking on it. You’ll now see the source code being displayed.

Below is the break down of source code for the template.c file.

[sourcecode language=’c’]#include
#include
#include
#include [/sourcecode]

These are our include files, which specify the libraries we are including in our source code. “stdio” represents the Standard Input/Output library which lets us print text to the screen, read and write files, etc. “stdlib” represents the Standard Utilities Library, and so on. You’ll need to use at least these 4 libraries when compiling code for the Wii.

[sourcecode language=’c’]static void *xfb = NULL;
static GXRModeObj *rmode = NULL;[/sourcecode]

We can skip these lines for now, they are just variables which are used to show video on the screen.

[sourcecode language=’c’]int main(int argc, char **argv) {[/sourcecode]

This line is the start of our “main” function, which is the first piece of code that is run after our libraries and variable definitions.

Most of the lines below this line have comments so it’s pretty easy to know what the each line does. For every application you develop that you will need all the lines from “VIDEO_Init();” to “if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();”. These lines aren’t really too important to focus on so we can skip them for now.

[sourcecode language=’c’]printf(“Hello World!”);[/sourcecode]

This line is saying that we would want to write “Hello World!” on to the screen.

[sourcecode language=’c’]while(1) {[/sourcecode]

We are starting an infinite loop which will run the below code.

[sourcecode language=’c’]WPAD_ScanPads();[/sourcecode]

This tells the system that we want to read the controller state. This will let us get information such as which buttons were pressed, which ones were let go, etc. You will always need to call this function when inside a loop, otherwise when you run your application on the Wii, you won’t be able do anything with the controller.

[sourcecode language=’c’]u32 pressed = WPAD_ButtonsDown(0);[/sourcecode]

As the comments for this line read, the “pressed” variable will tell us if anything was pressed on the controller. If we pressed

[sourcecode language=’c’]if ( pressed & WPAD_BUTTON_HOME ) exit(0);[/sourcecode]

Here we are just checking firstly, if a button was pressed (“pressed”) and secondly if the Home button was the button that was pressed (“& WPAD_BUTTON_HOME”). If both these conditions are true, then the application will be terminated (“exit(0);”).

[sourcecode language=’c’]VIDEO_WaitVSync();[/sourcecode]

WaitVSync just waits for the Vertical Sync from the TV screen. It’s exactly the same as the option that you have in some computer games. If you didn’t have this line of code and your application was doing a lot of graphics displaying and clearing of the screen then the screen would begin to flicker (although that wouldn’t happen in computer games, the game fps would just speed up).

[sourcecode language=’c’]}[/sourcecode]

This bracket ends the indefinite loop.

[sourcecode language=’c’]return 0;[/sourcecode]

All C programs must return 0 at the end of the program. If you don’t return 0 then the compiler will complain because it won’t know where the end of the program is.
Compiling the source code

So we know understand the source code. It will firstly initialise the video and controller, print out “Hello World!” to the screen and wait for us to press the Home button on the Wiimote to exit. Go ahead and press Alt + 1 to compile the project.

You will see the following text in the Output window:

[sourcecode language=’c’]> “make”
template.c
linking … template.elf
output … template.dol

> Process Exit Code: 0
> Time Taken: 00:02[/sourcecode]

As you can see, we have run the “make” command and it has compiled the template.c file which contained our source. It then outputs the machine executable format, an elf and dol, either can be used on the Wii.

Another command which is useful is the “clean” command which can be run by pressing Alt + 2. The clean command removes all traces of the compiled project, so that you can re-compile the project from scratch. It’s always a good idea to run the clean command and then recompile from scratch when you make major changes to any files.


Dealing with Compiling errors

Now we’ll talk about dealing with compiling errors. Most of the time when the compiler complains about something it’s usually right and gives us the line number where the problem occurs.

Say we forget to put the ; after assigning something to a variable, the compiler responds with:

[sourcecode language=’c’]c:/devkitpro/examples/wii/template/source/template.c: In function ‘main’:
c:/devkitpro/examples/wii/template/source/template.c:21: error: expected ‘;’ before ‘rmode'[/sourcecode]

So the compiler tells us which function this error occurred in and leads us close to the line in question. The second line is highlighted in light purple and if you click on it, it jumps you straight to a line that is close to the error.

The compiler can also give you warning about things which still will work but they are something you should look at. For example, if I have int test; and didn’t use it anywhere in the project, the compiler would say:

[sourcecode language=’c’]c:/devkitpro/examples/wii/template/source/template.c: In function ‘main’:
c:/devkitpro/examples/wii/template/source/template.c:52: warning: unused variable ‘test'[/sourcecode]

If you were to declare something like: int test = “ok”; which is incorrect as an integer can’t be a string then the compiler would say:

[sourcecode language=’c’]c:/devkitpro/examples/wii/template/source/template.c: In function ‘main’:
c:/devkitpro/examples/wii/template/source/template.c:52: warning: initialization makes integer from pointer without a cast[/sourcecode]

Most of the times reading what the compiler says does make sense. If it doesn’t you can always try to google the error message you are getting. Another thing to do if you’ve writing a whole heap of code all at once is to begin to comment out chunks of the code by using /* and */.

In the example below, the compiler will not compile the code that is inside the */ and */.

[sourcecode language=’c’]int test = 0;

/* if (test > 0) {
printf(“more than 0”);
} */[/sourcecode]

We’ve now got some fundamentals out of the way and now we can test out example project on the Wii. I’m assuming that you have the Homebrew Channel installed on your Wii. If not, you really should think about installing it, it makes things a lot easier.

In the C:\devkitPro\examples\Wii\template directory you will see a template.dol and template.elf file. Rename the template.elf file to boot.elf. Create a new directory on your SD card in the /apps/ directory called “template”. Copy your boot.elf file to the directory you created (/apps/template/).

Put the SD card back in your Wii and launch the Homebrew Channel. You should now see the directory you created in the listing of applications on the Homebrew Channel. Click on the application and click Load.

You will then see it show on the screen “Hello World!” and there you have it, you’ve compiled your first project for the Nintendo Wii.

Did I miss something or was my explanation not correct? Let me know so I can add the correction in the post.

34 Responses to “Tutorial 2: Makefiles, basics of C, compiling source code and dealing with errors”

  1. LOLDSFAN says:

    Once again thank you very much for the tutorial…Very much appreciated ;).

  2. octoroks says:

    man it work just like it said, man thanks, can’t wait for part 3

  3. niohubala says:

    Thank you very much for the first GOOD tutorial about getting started with wii programming. Especially the explanation about the MakeFile file was very interesting to me, a novice wii programmer.

    Thanks!

  4. Zoombus says:

    Instead of putting the dol file on the sd card and walking over to you wii, try this…..
    put wiiload.exe (it came w/ the hbrew channel install folder) into C:\devkitpro\msys\bin\

    open the homebrew channel, and once the globe icon is lit up (you’ll need a working internet connection), push the home button. you’ll get the hbrew channel menu, included Back, About and Exit. The the top left corner of this page you’ll see your wii’s ip adress. write it down.

    back on your computer, go to Control Panel, system, advanced system settings. Under the “advanced” tab, click environment variables. under “system variables” click new. For the name of this new variable, call it “WIILOAD” it has to be capital, and dont use the quotes. In the variable part put “tcp:yourIP”. Mine Looks Like this:

    Name: WIILOAD
    Variable: tcp:192.168.1.101

    click ok.

    back in programmers notepad, once you’re ready to test your code, start up the homebrew channel, wait ’til the globe icon is up, then go Tools –> Run. this will compile it, and send it straight to your wii. you’re welcome

  5. teknecal says:

    Zoombus: Good suggestion for the developers out there. I didn’t want to use this too soon as people might complain about it not working, network problems etc.

    Also just a note that your makefile chooses which program to execute when you are using Tools -> Run (Alt + R). As psoload is the default (at least it was for me), remember to change Run in your makefile to:

    run:
    wiiload $(TARGET).dol

  6. haven1433 says:

    Perhaps it’s just my computer, but I noticed that the “make” command only works if the last thing I opened was in the same directory as the makefile. Any tips or hints?

  7. Rob says:

    i’ve been looking for some tutorials for the wii for a long time. thanks! this was great and i’m planning to read the rest so write more too please!!

  8. Sam says:

    The part about comments is partly wrong:
    “In the example below, the compiler will not compile the code that is inside the */ and */.”

    Comments begin with /* not */

  9. Andy says:

    Finally got round to reading this.. thanks for the tutorial! Will start on the others over the next few days..

  10. Sardtok says:

    The precompiler calls don’t actually say anything, just include. No libraries are included.
    You do write down stdio and stdlib after, but you mention two others that have to be included.
    You do write down one include, with a missing hash mark, which I’m guessing won’t compile as include is a precompiler command.
    In that line though, you write down a ppc gamecube lib.

  11. gabriel says:

    how do I pass options to make?

    i’d like to make it compile to GC or WII with options. I can deal with the logic inside the makefile, but i have no idea how to pass things there besides env vars.

    I’d like to use command line arguments

  12. aledTH says:

    This isn’t working!

    Here’s the output:

    > “make”
    “make”: *** No targets specified and no makefile found. Stop.

    > Process Exit Code: 2
    > Time Taken: 00:00

    Why doesn’t it work?

  13. me! says:

    Would anyone be able to use this method to port StellaGC (Atari 2600 emu) to Wii? I’ll havea go one day, but my programming ability it pretty average, so it would probably take me weeks!

  14. aa55 says:

    (Excuse me if I make language mistakes but English is not my native language. However, I will do my best !)

    I’m not sure that learning C on the job is a good idea, but this tutorial is a good start.
    But, I’d like to comment some things.

    > int test = 5;
    > if (test == 5) { //do something }
    > else { //do something else }
    >
    > The double slashes (//) means that all the text after the slashes is a comment in the code.

    As you said, the text after the slashes is not interpreted, including the closing brackets : this code doesn’t compile.
    (and by the way, comments with double-slashes are not allowed in C).

    > int test = 0;
    > while (test printf(?ok?);
    > test++
    > }

    You forgot a semicolon after “test++”.

    > #include
    > #include
    > #include
    > #include

    Am I the only one to see four “#include” with nothing after it ?

    > if ( pressed & WPAD_BUTTON_HOME ) exit(0);
    > Here we are just checking firstly, if a button was pressed (?pressed?) and secondly if the Home button was the button that was pressed (?& WPAD_BUTTON_HOME?). If both these conditions are true, then the application will be terminated (?exit(0);?).

    You are confusing the ‘&’ and the ‘&&’ operators.
    The ‘&&’ operator returns TRUE if both conditions are TRUE.
    The ‘&’ operator returns the bitwise AND of two numbers.

    In fact, the number returned by PAD_ButtonsDown() is a “bit array”. Each bit of this number describes the state of one button : 1 if it’s pressed ; 0 if it’s released.
    When all buttons are released, the variable “pressed” equals 0.
    Then, if I press the button A, the bit corresponding to this button (bit #3) will be set, and PAD_ButtonsDown() will return 00000001000 (in binary).
    If I press “HOME” (bit #5) while A is kept pressed, PAD_ButtonsDown() will return 00000101000.

    Now, if I want to know if the A button is pressed, the easiest way is to use a bitwise AND (operator ‘&’) with “the bit corresponding to the A button” (in this case : 00000001000).
    If the button A is pressed, I will get a non-null value (00000001000 in this case). Else, I will get 0.
    And as you might know, the code after an “if” is run if you give it a non-null value. We could write “if(pressed & WPAD_BUTTON_HOME != 0)” to make this more precise.

    I hope it was understandable.

    > All C programs must return 0 at the end of the program.

    main() must return 0 only if the programm succeed (and EXIT_FAILURE otherwise).

    > If you don’t return 0 then the compiler will complain because it won’t know where the end of the program is.

    It’s not because he doesn’t know where the end of the program is (he knows it’s when he encounters the closing bracket of the main).
    It’s rather because you explicitly said that your main() returned an ‘int’, and the compiler doesn’t like people who don’t keep their promises.

    > Another thing to do if you?ve writing a whole heap of code all at once is to begin to comment out chunks of the code by using /* and */.

    But if you have already comments in this heap of code, this trick will not work.

    I prefer the use of #ifdef :
    #ifdef 0
    /* Some code */
    #endif

    > Perhaps it’s just my computer, but I noticed that the “make” command only works if the last thing I opened was in the same directory as the makefile. Any tips or hints?

    “make” process only files which have been modified since the last compilation. So if you don’t modify any file, it would be a loss of time to recompile them.

  15. KIDD says:

    I get this error every time:

    “template.c
    powerpc-gekko-gcc.exe: CreateProcess: No such file or directory
    make[1]: *** [template.o] Error 1
    “make”: *** [build] Error 2″

  16. KIDD says:

    ah sorry,
    I fixed that problem by using the codemii template:P
    but now i get this error;

    No rule to make target `c:/devkitPro/examples/wii/GRRLIB-v1.0/template/source/GRRLIB.c’, needed by `GRRLIB.o’

    Thanks for the help:D

  17. GM says:

    Some excellent tips here… very nearly solved my problem!

    I’ve just started playing around developing stuff for the Wii. Haven’t done much C for years and so many other languages in between. Very inspired by a lot of the stuff found on the homebrew browser. Used to write games on an old BBC many years ago so very enthusiastic about it all again – at my age it’s hard to get enthusiastic about anything!

    Big thanks to all who made homebrew on the Wii possible. It’s literally giving me a new lease of life!

  18. Riven says:

    Sorry for the dumb question, but what’s the conversion type character for double in the printf() function? The tutorial says %i for integers, %f for float, and %l for long, but I can’t figure out the others. If someone knows a list with boolean, char, and the others it would help me out a lot.

  19. Timptation says:

    I’m loving these tutorials, but is there a way to use C++ instead of C? I’m not so used to C unfortunately and would love to “upgrade”…

  20. I’ve been using your site for a while for my wii programming, however for about two months, I didn’t compile anything for the wii. Recently, I’ve decided to start programming for the wii again, bu for some reason it will no longer compile, instead outputting the error:
    “make”: *** No targets specified and no makefile found. Stop.

    I’ve tried reinstalling DevKitPro, but nothing I do seems to change anything. You have any suggestions?

  21. Nevermind, I figured out what that problem was. I had named the makefile “MAKEFILE”, so it couldn’t seem to find it. Now I’ve run into another problem:
    [code]
    “make”
    linking … wiiMediaPlayer.elf
    c:/devkitpro/devkitppc/bin/../lib/gcc/powerpc-gekko/4.2.4/../../../../powerpc-gekko/lib/crtmain.o: In function `__crtmain’:
    e:/projects/devkitPro/buildscripts/newlib-1.17.0/libgloss/rs6000/crtmain.c:18: undefined reference to `main’
    collect2: ld returned 1 exit status
    make[1]: *** [/c/devkitPro/examples/wii/wiiMediaPlayer/wiiMediaPlayer.elf] Error 1
    “make”: *** [build] Error 2
    [/code]

    Please note that all this is, is the template file linked to in your December 25 comment.

  22. Nevermind. I got that one fixed too. Sorry for tripleposting.

  23. Michele says:

    I’ve followed your istructions, but when i try to compile i get these errors:

    > “make”
    MAKE Version 5.2 Copyright (c) 1987, 1998 Inprise Corp.
    Error makefile 7: Command syntax error
    Error makefile 8: Command syntax error
    Error makefile 9: Command syntax error
    Error makefile 11: Command syntax error
    Error makefile 49: Command syntax error
    Error makefile 71: Command syntax error
    Error makefile 73: Command syntax error
    Error makefile 75: Command syntax error
    Error makefile 99: Command syntax error
    Error makefile 100: Command syntax error
    Error makefile 101: Command syntax error
    Error makefile 114: Command syntax error
    Error makefile 121: Colon expected
    Error makefile 122: Colon expected
    Error makefile 132: Command syntax error
    Error makefile 135: Command syntax error
    *** 16 errors during make ***

    > Process Exit Code: 1
    > Time Taken: 00:00

    Looking at the line 7:

    $(error “Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC”)

    I’ve looked at the enviromet vars and they’re set correctly.

    What should I do?

    Please help!

  24. Trav41514 says:

    I think you made a small error in the commenting section. You state that everything in the */ and */ will not be compilied. This would be true if you said /* and */ 😀

    A excellent tutorial, and I can’t wait for the updates 9/10

  25. Gregory Yeghiyan says:

    I’m the newest commenter right? I’m probably the first one to read this guide since 2009

Leave a Reply for teknecal