2
votes

I'm using the MPLAB IDE and the XC8 compiler for a C project for PIC18 devices. I'm building a project with multiple source files and don't know how to make the structure.

In the project, I have the following things:

  • A file main.c where the main code is located. From here, several files are included:
    • xc.h: to define chip-specific variables and so
    • stdlib.h, stdio.h, plib.h, delays.h: for the compiler's functions
    • enc28j60.h: a homebrew file with definitions and prototypes
  • A file enc28j60.c, where the functions of the prototypes in enc28j60.h go

I cannot compile enc28j60.c as standalone file because it depends on definitions in main.c.

I have a few questions on how to set this project up:

  1. Should I add enc28j60.c to the source files of my MPLAB project? If I do this, MPLAB tries to compile the file, which fails. If I don't do this, the linker cannot find the symbols that are defined in enc28j60.c and prototyped in enc28j60.h.
  2. Should I #include enc28j60.c from somewhere? If not, how does MPLAB know where to get the file?
  3. Should I add enc28j60.h to the header files of my MPLAB project?
  4. Should I #include enc28j60.h from somewhere? Right now, I do this in main.c, after the definitions enc28j60.h needs in order to run (and not throw #errors).
2
Never, ever include C files. Including is for headers. You have to link the object files generated from the individual source files. I. e., <C_COMPILER> -c foo.c -o foo.o then <C_COMPILER> -c bar.c -o bar.o, finally <LINKER> foo.o bar.o -o binary_nameuser529758
@H2CO3 thanks, but how can I create object files from a file that cannot be compiled as a standalone file? "I cannot compile enc28j60.c as standalone file because it depends on definitions in main.c."user1544337
Definitions? You mean declarations, right? In this case, your design is bad and you should move the declarations in question to another, globally accessible header.user529758
@H2CO3 so it isn't possible, what I want? In that case, you can write that as an answer :)user1544337
It is. To quote myself: "you should move the declarations in question to another, globally accessible header"user529758

2 Answers

2
votes

I managed to get this working by modifying my library and header files a bit.

At first, I added a file main.h where all the prototypes, #defines and #includes would go. Then, in every .h, file, I added this on top:

#ifndef SOME_LIB_IDENTIFIER   // makes sure the lib only gets included once,
#define SOME_LIB_IDENTIFIER   // has to be specific for every lib

#include "main.h"             // to make sure everything's initialized (this line of course not in main.h)

And the last line of every .h file would be:

#endif

I added #include "enc28j60.h" to the top of the enc28j60.c file. This file now can be compiled.

In main.h, I added includes for xc.h, plib.h, stdlib.h, stdio.h and enc28j60.h. I nowhere included .c files.

I added both the main and enc28j60 header and source files to my MPLAB project. The source files get compiled well, both. The result is linked together.

In short

  • Add a main.h where all prototypes, #defines and #includes go
  • Add a header and footer to all your header file to make sure they're only included once. Also include main.h from these headers, to make sure every file uses the same definitions
  • Include a source file's corresponding .h file at the very first line of your source file. Do not include .c files
  • Add all header and source files (that are not built into the compiler) to your MPLAB project
  • Build (F10) should compile all files and link them together correctly
1
votes

Don't include .c files. Include headers only. If you have declarations to be shared between files, put them in a separate header, and include that header whenever you need it.

After compiling each individual source file, link the resulting object files together. This involves the invocation of the compiler on all of the source files, then a one-time invocation of the linker on the object files (with supplemental libraries, etc.).