Spliting into several source files.

SGDK only sub forum

Moderator: Stef

Post Reply
orlanrod
Very interested
Posts: 99
Joined: Fri Sep 25, 2015 7:46 pm

Spliting into several source files.

Post by orlanrod » Mon Oct 05, 2015 11:10 pm

The main file is getting a little bit cluttered. I was wondering if it is possible to put some source into another file, and include it in the main source?
Would that perform worse or not?

Thanks.

mikejmoffitt
Very interested
Posts: 86
Joined: Fri Sep 25, 2015 4:16 pm

Re: Spliting into several source files.

Post by mikejmoffitt » Tue Oct 06, 2015 12:35 am

That is absolutely fine and considered best practice for splitting code across areas of functionality and data.

You will want a header for every source file you create to declare your functions and data structures. This tells the compiler "there exist these functions" so when other files #include your header, they will be able to link to the functions you wrote and use them. Here is a skeleton example:

foo.h

Code: Select all

// Include guards prevent these forward declarations from being interpreted multiple times by the compiler by using the preprocessor.
// Without it, you will get errors about multiple definitions. 
#ifndef FOO_H
#define FOO_H
// Function declarations go here, as well as data structures you'd like to make accessable by including this file.
// If you are going to reference any SGDK stuff here, you'll need this line:
#include <genesis.h>
// Because of the include guards it is okay to include genesis.h everywhere that you need it. 

// A simple struct describing a "foo" object. Just stores three u16 variables (unsigned short; 16-bit word)
typedef struct foo_struct foo_struct;
struct foo_struct 
{
  u16 bar;
  u16 pos[2];
}

// Do something to a foo struct
void foo_func(foo_struct *f);

#endif
In your C file, you define the functions you declared earlier. This is what allows the C compiler to generate object code which your linker connects to calls you've made elsewhere. If you write code in your C file without declaring it in the header, it is considered static by default - only other things in that same compilation unit (this C file, here) can see or use it. For small support functions, this is good practice as it keeps your global namespace from being cluttered, and it also allows the C compiler's optimization to work better. It is good to declare functions explicitly static when appropriate.

foo.c:

Code: Select all

// Include your declarations from before, as you'll be defining them here
#include "foo.h"

void foo_func(foo_struct *f)
{
    // What this code does isn't too important - just that it is a function that manipulates this pointer to the foo struct.
    f->bar = f->bar * 2;
    f->pos[0]++;
    f->pos[1]--;
}

In your main file, you may now #include "foo.h" in order to use the code you wrote in foo.c. Header files are what you include in other files. They tell the compiler about functions and data, and at linker time your calls are linked to those functions. #including a C file is technically possible, but it is not the correct way to do things and you will get very compounded errors.

orlanrod
Very interested
Posts: 99
Joined: Fri Sep 25, 2015 7:46 pm

Re: Spliting into several source files.

Post by orlanrod » Tue Oct 06, 2015 5:50 am

mikejmoffitt wrote:That is absolutely fine and considered best practice for splitting code across areas of functionality and data.

You will want a header for every source file you create to declare your functions and data structures. This tells the compiler "there exist these functions" so when other files #include your header, they will be able to link to the functions you wrote and use them. Here is a skeleton example:

foo.h

Code: Select all

// Include guards prevent these forward declarations from being interpreted multiple times by the compiler by using the preprocessor.
// Without it, you will get errors about multiple definitions. 
#ifndef FOO_H
#define FOO_H
// Function declarations go here, as well as data structures you'd like to make accessable by including this file.
// If you are going to reference any SGDK stuff here, you'll need this line:
#include <genesis.h>
// Because of the include guards it is okay to include genesis.h everywhere that you need it. 

// A simple struct describing a "foo" object. Just stores three u16 variables (unsigned short; 16-bit word)
typedef struct foo_struct foo_struct;
struct foo_struct 
{
  u16 bar;
  u16 pos[2];
}

// Do something to a foo struct
void foo_func(foo_struct *f);

#endif
In your C file, you define the functions you declared earlier. This is what allows the C compiler to generate object code which your linker connects to calls you've made elsewhere. If you write code in your C file without declaring it in the header, it is considered static by default - only other things in that same compilation unit (this C file, here) can see or use it. For small support functions, this is good practice as it keeps your global namespace from being cluttered, and it also allows the C compiler's optimization to work better. It is good to declare functions explicitly static when appropriate.

foo.c:

Code: Select all

// Include your declarations from before, as you'll be defining them here
#include "foo.h"

void foo_func(foo_struct *f)
{
    // What this code does isn't too important - just that it is a function that manipulates this pointer to the foo struct.
    f->bar = f->bar * 2;
    f->pos[0]++;
    f->pos[1]--;
}

In your main file, you may now #include "foo.h" in order to use the code you wrote in foo.c. Header files are what you include in other files. They tell the compiler about functions and data, and at linker time your calls are linked to those functions. #including a C file is technically possible, but it is not the correct way to do things and you will get very compounded errors.

Ah okay. But I am getting this error (the player.h is in a folder called hed, inside the project folder.)

||=== Build: default in cosmicbrow (compiler: Sega Genesis Compiler) ===|
src\main.c|5|player.h: No such file or directory|

tryphon
Very interested
Posts: 316
Joined: Sat Aug 17, 2013 9:38 pm
Location: France

Re: Spliting into several source files.

Post by tryphon » Tue Oct 06, 2015 7:55 am

And you have a player.h file ? Just next to your main.c ?

orlanrod
Very interested
Posts: 99
Joined: Fri Sep 25, 2015 7:46 pm

Re: Spliting into several source files.

Post by orlanrod » Tue Oct 06, 2015 6:55 pm

tryphon wrote:And you have a player.h file ? Just next to your main.c ?
This is how my project structure looks like. It's strange that gfx.h works but trying player.h does not see it.

Image

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Re: Spliting into several source files.

Post by Stef » Tue Oct 06, 2015 7:14 pm

Change your "header" folder name to "inc" then it should work.
SGDK uses the following naming convention:
- / or /src --> source files
- / or /inc --> include files
- / or /res --> resource files

orlanrod
Very interested
Posts: 99
Joined: Fri Sep 25, 2015 7:46 pm

Re: Spliting into several source files.

Post by orlanrod » Tue Oct 06, 2015 8:35 pm

tryphon wrote:And you have a player.h file ? Just next to your main.c ?
Nevermind, i fixed it by naming the hed folder to inc like Stef told me. Thanks for the help though!

orlanrod
Very interested
Posts: 99
Joined: Fri Sep 25, 2015 7:46 pm

Re: Spliting into several source files.

Post by orlanrod » Tue Oct 06, 2015 8:35 pm

Stef wrote:Change your "header" folder name to "inc" then it should work.
SGDK uses the following naming convention:
- / or /src --> source files
- / or /inc --> include files
- / or /res --> resource files
Yep, that worked great. Thanks!

mikejmoffitt
Very interested
Posts: 86
Joined: Fri Sep 25, 2015 4:16 pm

Re: Spliting into several source files.

Post by mikejmoffitt » Tue Oct 06, 2015 11:06 pm

For reference, the reason "inc" works is because the Makefile is adding it to the header search path. You could have added -Ihed to your Makefile, but 'inc' and 'include' are de-facto standard names so it is best to use those. Your project root would have worked as well but it's more organized to keep folders like this.

Post Reply