Page 1 of 1

Multiple definition of, error "foo" indeclarated...

Posted: Sun Jan 27, 2019 8:00 pm
by deleted8917
I'm restructuring my code, but when I compile I have a lot of errors, mostly from the linker;
Linker:

Code: Select all

kernel/serial.o: In function `outb':
/mnt/c/Users/user/Desktop/osproject/kernel/kernel.h:47: multiple definition of `init_serial'
kmain.o:/mnt/c/Users/user/Desktop/osproject/kernel/kernel.h:58: first defined here
kernel/serial.o: In function `inb':
/mnt/c/Users/user/Desktop/osproject/kernel/kernel.h:54: multiple definition of `serial_received'
kmain.o:/mnt/c/Users/user/Desktop/osproject/kernel/kernel.h:65: first defined here
kernel/serial.o: In function `inb':
/mnt/c/Users/user/Desktop/osproject/kernel/kernel.h:54: multiple definition of `read_serial'
kmain.o:/mnt/c/Users/user/Desktop/osproject/kernel/kernel.h:65: first defined here
kernel/serial.o: In function `inb':
/mnt/c/Users/user/Desktop/osproject/kernel/kernel.h:54: multiple definition of `is_transmit_empty'
kmain.o:/mnt/c/Users/user/Desktop/osproject/kernel/kernel.h:65: first defined here
kernel/serial.o: In function `write_serial':
/mnt/c/Users/user/Desktop/osproject/kernel/serial.c:37: multiple definition of `write_serial'
kmain.o:/mnt/c/Users/user/Desktop/osproject/kernel/serial.h:40: first defined here
collect2: error: ld returned 1 exit status
compiler:

Code: Select all

In file included from kmain.c:5:0:
kernel/isrs.h: In function ‘fault_handler’:
kernel/isrs.h:142:22: error: ‘LIGHTGRAY’ undeclared (first use in this function)
         settextcolor(LIGHTGRAY, RED);
                      ^
kernel/isrs.h:142:22: note: each undeclared identifier is reported only once for each function it appears in
kernel/isrs.h:142:33: error: ‘RED’ undeclared (first use in this function)
         settextcolor(LIGHTGRAY, RED);
                                 ^
kmain.c: In function ‘kernelmain’:
kmain.c:24:38: error: expected ‘)’ before ‘nl’
     println("asd ����� �"nl);
                                      ^
kmain.c:33:13: error: ‘nl’ undeclared (first use in this function)
     println(nl);
             ^
But nl, LIGHTGRAY and RED macros exists!
Here's the code: https://gitlab.com/hextakatt/experimentalos

Re: Multiple definition of, error "foo" indeclarated...

Posted: Sun Jan 27, 2019 8:39 pm
by alexfru
Multiple definitions are typically a result of defining non-static variables/functions in .h files that are included in several .c files.

Re: Multiple definition of, error "foo" indeclarated...

Posted: Mon Jan 28, 2019 10:24 am
by Schol-R-LEA
Looking at the header file isrs.h in your Gitlab repo, I see that the functions in question are in the header itself; this means that they get redefined every time the header is used, which will cause this problem when the linker then has to find which function to attach to which function name. See the wiki page Why function implementations shouldn't be put In header files for a detailed (if tongue in cheek) explanation of the topic, but the short solution is to never put the body of a non-inline function into the header itself.

In this case, since most of these functions are used in several places and are not the sort of tiny ones suited for inserting directly into code repeatedly (i.e., ones under four or five lines of code), simply declaring them as inline probably isn't the best idea. This means you will want to extract them from the header and put them in a source file (e.g., isrs.c would make sense) and add them using the linker. If some of them are used only once, the current C standard does have an inline clause you can use to have the function calls replaced by the body of the function (I can see you've used that in your kernel.h file), which would allow you to keep them in the header (though I would still recommend moving them, as inlining large functions can have odd side effects).

Oh, and for the exception handler, you might want to use inline assembly to insert a hlt instruction in that loop; otherwise, the CPU will be spinning at full tilt, doing nothing but still burning energy and generating excessive heat. And you really, really don't want to declare that as an inline function, because its sole purpose is to be called implicitly by the interrupt handler in multiple places.

I can't say for certain why it isn't finding the defined macros; you do have the terminal.h header included in both of those, but there is no such header file - you have a terminal.c but no terminal.h, which I would have expected to cause a 'missing file' error, too.

I suggest the following as the terminal.h file:

Code: Select all

#ifndef TERMINAL_H
#define TERMINAL_H

#define BLACK 0
#define BLUE 1
#define GREEN 2
#define CYAN 3
#define RED 4
#define MAGENTA 5
#define BROWN 6
#define LIGHTGRAY 7
#define DARKGRAY 8
#define LIGHTBLUE 9
#define LIGHTGREEN 10
#define LIGHTCYAN 11
#define LIGHTRED 12
#define LIGHTMAGENTA 13
#define YELLOW 14
#define WHITE 15
#define nl "\r\n"

/* you will want to remove these from 'kernel.h' anyway */
void scroll(void);
void move_csr(void);
void gotoxy(int x, int y);
void clear_screen(void);
void putch(unsigned char c);
void rawputch(unsigned char c);
void println(char *text);
void settextcolor(unsigned char forecolor, unsigned char backcolor);
void init_video(void);
unsigned char getch(void);
char *readln(char *str, int maxnumchars);
char *itoa(int val, int base);

#endif
Similarly for timer.h:

Code: Select all

#ifndef TIMER_H
#define TIMER_H

void timer_phase(int hz);
void timer_handler(struct regs *r);
void timer_install();
void timer_wait(int ticks);
void sleep(int seconds);

#endif
... and serial.h:

Code: Select all

#ifndef SERIAL_H
#define SERIAL_H

void init_serial(void);
int serial_received(void);
unsigned char read_serial(void);
int is_transmit_empty(void);
void write_serial(char a);

#endif
This makes the code more modular and fine-grained. It also means you don't need to include kernel.h everywhere - while most of these files will still need it anyway, others you develop later might not need everything thrown into one big pile.

Finally, you can't use the normal stddef.h and stdint.h as defined by the compiler - those are versions designed for applications, not kernels.

Re: Multiple definition of, error "foo" indeclarated...

Posted: Mon Jan 28, 2019 12:04 pm
by Octocontrabass
Schol-R-LEA wrote:Finally, you can't use the normal stddef.h and stdint.h as definied by the compiler - those are versions designed for applications, not kernels.
Why do you say that? Freestanding headers are intended to be usable everywhere.

Re: Multiple definition of, error "foo" indeclarated...

Posted: Mon Jan 28, 2019 1:16 pm
by deleted8917
Octocontrabass wrote:
Schol-R-LEA wrote:Finally, you can't use the normal stddef.h and stdint.h as definied by the compiler - those are versions designed for applications, not kernels.
Why do you say that? Freestanding headers are intended to be usable everywhere.
Correct. I use stddef and stdint without problems, since that libraries are just typedef definitions...

Re: Multiple definition of, error "foo" indeclarated...

Posted: Mon Jan 28, 2019 6:05 pm
by Schol-R-LEA
Octocontrabass wrote:
Schol-R-LEA wrote:Finally, you can't use the normal stddef.h and stdint.h as definied by the compiler - those are versions designed for applications, not kernels.
Why do you say that? Freestanding headers are intended to be usable everywhere.
Ugh, brain fart time, sorry about that. I'm not sure why I said that.

Re: Multiple definition of, error "foo" indeclarated...

Posted: Tue Jan 29, 2019 9:17 pm
by deleted8917
I forgot to say that now it works, thanks!

Re: Multiple definition of, error "foo" indeclarated...

Posted: Wed Jan 30, 2019 1:09 pm
by Schol-R-LEA
hextakatt wrote:I forgot to say that now it works, thanks!
Good to hear. Do you intend to commit the current version to your repo?